mirror of
https://github.com/Relintai/godot_voxel.git
synced 2024-11-19 02:47:18 +01:00
Use VisualServer directly for mesh instances
This commit is contained in:
parent
a371e7fc9a
commit
6419e78fc2
@ -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<MeshInstance>();
|
||||
}
|
||||
|
||||
// Helper
|
||||
VoxelBlock *VoxelBlock::create(Vector3i bpos, Ref<VoxelBuffer> buffer, unsigned int size) {
|
||||
const int bs = size;
|
||||
@ -17,6 +8,7 @@ VoxelBlock *VoxelBlock::create(Vector3i bpos, Ref<VoxelBuffer> 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<VoxelBuffer> 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> mesh, Ref<World> 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;
|
||||
}
|
||||
|
@ -12,14 +12,18 @@ class VoxelBlock {
|
||||
public:
|
||||
Ref<VoxelBuffer> voxels; // SIZE*SIZE*SIZE voxels
|
||||
Vector3i pos;
|
||||
NodePath mesh_instance_path;
|
||||
|
||||
static VoxelBlock *create(Vector3i bpos, Ref<VoxelBuffer> buffer, unsigned int size);
|
||||
|
||||
MeshInstance *get_mesh_instance(const Node &root);
|
||||
void set_mesh(Ref<Mesh> mesh, Ref<World> world);
|
||||
|
||||
private:
|
||||
VoxelBlock();
|
||||
|
||||
Vector3i _position_in_voxels;
|
||||
|
||||
Ref<Mesh> _mesh;
|
||||
RID _mesh_instance;
|
||||
};
|
||||
|
||||
#endif // VOXEL_BLOCK_H
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
|
||||
VoxelTerrain::VoxelTerrain()
|
||||
: Node(), _generate_collisions(true) {
|
||||
: Spatial(), _generate_collisions(true) {
|
||||
|
||||
_map = Ref<VoxelMap>(memnew(VoxelMap));
|
||||
_mesher = Ref<VoxelMesher>(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<Mesh>();
|
||||
|
||||
if (is_mesh_empty(mesh)) {
|
||||
if (mesh_instance) {
|
||||
mesh_instance->set_mesh(Ref<Mesh>());
|
||||
}
|
||||
} 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> world = get_world();
|
||||
block->set_mesh(mesh, world);
|
||||
}
|
||||
|
||||
//void VoxelTerrain::block_removed(VoxelBlock & block) {
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user