mirror of
https://github.com/Relintai/godot_voxel.git
synced 2025-05-01 17:57:55 +02:00
Use VisualServer directly for mesh instances
This commit is contained in:
parent
a371e7fc9a
commit
6419e78fc2
@ -1,14 +1,5 @@
|
|||||||
#include "voxel_block.h"
|
#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
|
// Helper
|
||||||
VoxelBlock *VoxelBlock::create(Vector3i bpos, Ref<VoxelBuffer> buffer, unsigned int size) {
|
VoxelBlock *VoxelBlock::create(Vector3i bpos, Ref<VoxelBuffer> buffer, unsigned int size) {
|
||||||
const int bs = size;
|
const int bs = size;
|
||||||
@ -17,6 +8,7 @@ VoxelBlock *VoxelBlock::create(Vector3i bpos, Ref<VoxelBuffer> buffer, unsigned
|
|||||||
|
|
||||||
VoxelBlock *block = memnew(VoxelBlock);
|
VoxelBlock *block = memnew(VoxelBlock);
|
||||||
block->pos = bpos;
|
block->pos = bpos;
|
||||||
|
block->_position_in_voxels = bpos * size;
|
||||||
|
|
||||||
block->voxels = buffer;
|
block->voxels = buffer;
|
||||||
//block->map = ↦
|
//block->map = ↦
|
||||||
@ -25,5 +17,42 @@ VoxelBlock *VoxelBlock::create(Vector3i bpos, Ref<VoxelBuffer> buffer, unsigned
|
|||||||
|
|
||||||
VoxelBlock::VoxelBlock()
|
VoxelBlock::VoxelBlock()
|
||||||
: voxels(NULL) {
|
: 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:
|
public:
|
||||||
Ref<VoxelBuffer> voxels; // SIZE*SIZE*SIZE voxels
|
Ref<VoxelBuffer> voxels; // SIZE*SIZE*SIZE voxels
|
||||||
Vector3i pos;
|
Vector3i pos;
|
||||||
NodePath mesh_instance_path;
|
|
||||||
|
|
||||||
static VoxelBlock *create(Vector3i bpos, Ref<VoxelBuffer> buffer, unsigned int size);
|
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:
|
private:
|
||||||
VoxelBlock();
|
VoxelBlock();
|
||||||
|
|
||||||
|
Vector3i _position_in_voxels;
|
||||||
|
|
||||||
|
Ref<Mesh> _mesh;
|
||||||
|
RID _mesh_instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VOXEL_BLOCK_H
|
#endif // VOXEL_BLOCK_H
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
|
|
||||||
VoxelTerrain::VoxelTerrain()
|
VoxelTerrain::VoxelTerrain()
|
||||||
: Node(), _generate_collisions(true) {
|
: Spatial(), _generate_collisions(true) {
|
||||||
|
|
||||||
_map = Ref<VoxelMap>(memnew(VoxelMap));
|
_map = Ref<VoxelMap>(memnew(VoxelMap));
|
||||||
_mesher = Ref<VoxelMesher>(memnew(VoxelMesher));
|
_mesher = Ref<VoxelMesher>(memnew(VoxelMesher));
|
||||||
@ -306,6 +306,8 @@ void VoxelTerrain::_notification(int p_what) {
|
|||||||
make_all_view_dirty();
|
make_all_view_dirty();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// TODO Listen for transform changes
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
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);
|
_map->get_buffer_copy(_map->block_to_voxel(block_pos) - Vector3i(1, 1, 1), nbuffer, 0x3);
|
||||||
VOXEL_PROFILE_END("block_extraction")
|
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
|
// TODO Re-use existing meshes to optimize memory cost
|
||||||
|
|
||||||
// Build cubic parts of the mesh
|
// Build cubic parts of the mesh
|
||||||
@ -449,36 +449,11 @@ void VoxelTerrain::update_block_mesh(Vector3i block_pos) {
|
|||||||
// Build smooth parts of the mesh
|
// Build smooth parts of the mesh
|
||||||
_mesher_smooth->build(nbuffer, Voxel::CHANNEL_ISOLEVEL, 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)) {
|
Ref<World> world = get_world();
|
||||||
if (mesh_instance) {
|
block->set_mesh(mesh, world);
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//void VoxelTerrain::block_removed(VoxelBlock & block) {
|
//void VoxelTerrain::block_removed(VoxelBlock & block) {
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
// Infinite static terrain made of voxels.
|
// Infinite static terrain made of voxels.
|
||||||
// It is loaded around VoxelTerrainStreamers.
|
// It is loaded around VoxelTerrainStreamers.
|
||||||
class VoxelTerrain : public Node /*, public IVoxelMapObserver*/ {
|
class VoxelTerrain : public Spatial /*, public IVoxelMapObserver*/ {
|
||||||
GDCLASS(VoxelTerrain, Node)
|
GDCLASS(VoxelTerrain, Spatial)
|
||||||
public:
|
public:
|
||||||
VoxelTerrain();
|
VoxelTerrain();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user