When a block is not visible, remove it from world instead

master
Marc Gilleron 2020-01-07 02:04:24 +00:00
parent 051034fc51
commit badf3876c3
3 changed files with 38 additions and 35 deletions

View File

@ -71,6 +71,19 @@ VoxelBlock::VoxelBlock() {
VoxelBlock::~VoxelBlock() {
}
void VoxelBlock::set_world(Ref<World> p_world) {
if (_world != p_world) {
_world = p_world;
// To update world. I replaced visibility by presence in world because Godot 3 culling performance is horrible
_set_visible(_visible && _parent_visible);
if (_static_body.is_valid()) {
_static_body.set_world(*p_world);
}
}
}
void VoxelBlock::set_mesh(Ref<Mesh> mesh, Spatial *node, bool generate_collision, Array surface_arrays, bool debug_collision) {
// TODO Don't add mesh instance to the world if it's not visible.
// I suspect Godot is trying to include invisible mesh instances into the culling process,
@ -80,16 +93,14 @@ void VoxelBlock::set_mesh(Ref<Mesh> mesh, Spatial *node, bool generate_collision
if (mesh.is_valid()) {
ERR_FAIL_COND(node == nullptr);
Ref<World> world = node->get_world();
ERR_FAIL_COND(world.is_null());
ERR_FAIL_COND(node->get_world() != _world);
Transform transform(Basis(), _position_in_voxels.to_vec3());
if (!_mesh_instance.is_valid()) {
// Create instance if it doesn't exist
_mesh_instance.create();
_mesh_instance.set_world(*world);
_mesh_instance.set_visible(_visible);
set_mesh_instance_visible(_mesh_instance, _visible && _parent_visible);
}
_mesh_instance.set_mesh(mesh);
@ -108,14 +119,14 @@ void VoxelBlock::set_mesh(Ref<Mesh> mesh, Spatial *node, bool generate_collision
if (!_static_body.is_valid()) {
_static_body.create();
_static_body.set_world(*world);
_static_body.set_world(*_world);
_static_body.set_attached_object(node);
_static_body.set_transform(transform);
} else {
_static_body.remove_shape(0);
}
_static_body.add_shape(shape);
_static_body.set_debug(debug_collision, *world);
_static_body.set_debug(debug_collision, *_world);
_static_body.set_shape_enabled(0, _visible);
}
@ -138,19 +149,16 @@ void VoxelBlock::set_mesh(Ref<Mesh> mesh, Spatial *node, bool generate_collision
// }
}
void VoxelBlock::set_transition_mesh(Ref<Mesh> mesh, int side, Ref<World> world) {
void VoxelBlock::set_transition_mesh(Ref<Mesh> mesh, int side) {
DirectMeshInstance &mesh_instance = _transition_mesh_instances[side];
if (mesh.is_valid()) {
ERR_FAIL_COND(world.is_null());
if (!mesh_instance.is_valid()) {
// Create instance if it doesn't exist
mesh_instance.create();
mesh_instance.set_world(*world);
mesh_instance.set_visible(_visible && _is_transition_visible(side));
set_mesh_instance_visible(mesh_instance, _visible && _parent_visible && _is_transition_visible(side));
}
Transform transform(Basis(), _position_in_voxels.to_vec3());
@ -186,20 +194,6 @@ VoxelBlock::MeshState VoxelBlock::get_mesh_state() const {
return _mesh_state;
}
void VoxelBlock::set_world(World *world) {
if (_mesh_instance.is_valid()) {
_mesh_instance.set_world(world);
}
for (int i = 0; i < _transition_mesh_instances.size(); ++i) {
if (_transition_mesh_instances[i].is_valid()) {
_transition_mesh_instances[i].set_world(world);
}
}
if (_static_body.is_valid()) {
_static_body.set_world(world);
}
}
void VoxelBlock::set_visible(bool visible) {
if (_visible == visible) {
return;
@ -214,11 +208,12 @@ bool VoxelBlock::is_visible() const {
void VoxelBlock::_set_visible(bool visible) {
if (_mesh_instance.is_valid()) {
_mesh_instance.set_visible(visible);
set_mesh_instance_visible(_mesh_instance, visible);
}
for (int dir = 0; dir < _transition_mesh_instances.size(); ++dir) {
if (_transition_mesh_instances[dir].is_valid()) {
_transition_mesh_instances[dir].set_visible(visible & _is_transition_visible(dir));
for (unsigned int dir = 0; dir < _transition_mesh_instances.size(); ++dir) {
DirectMeshInstance &mi = _transition_mesh_instances[dir];
if (mi.is_valid()) {
set_mesh_instance_visible(mi, visible && _is_transition_visible(dir));
}
}
if (_static_body.is_valid()) {
@ -269,7 +264,7 @@ void VoxelBlock::set_transition_mask(uint8_t m) {
for (int dir = 0; dir < Cube::SIDE_COUNT; ++dir) {
DirectMeshInstance &mi = _transition_mesh_instances[dir];
if ((diff & (1 << dir)) && mi.is_valid()) {
mi.set_visible(_visible & _is_transition_visible(dir));
set_mesh_instance_visible(mi, _visible && _parent_visible && _is_transition_visible(dir));
}
}
}

View File

@ -33,8 +33,9 @@ public:
// Visuals and physics
void set_world(Ref<World> p_world);
void set_mesh(Ref<Mesh> mesh, Spatial *node, bool generate_collision, Array surface_arrays, bool debug_collision);
void set_transition_mesh(Ref<Mesh> mesh, int side, Ref<World> world);
void set_transition_mesh(Ref<Mesh> mesh, int side);
bool has_mesh() const;
void set_shader_material(Ref<ShaderMaterial> material);
@ -43,8 +44,6 @@ public:
void set_mesh_state(MeshState ms);
MeshState get_mesh_state() const;
void set_world(World *world);
void set_visible(bool visible);
bool is_visible() const;
@ -66,9 +65,16 @@ private:
VoxelBlock();
void _set_visible(bool visible);
void _update_transition_visibility();
inline bool _is_transition_visible(int side) const { return _transition_mask & (1 << side); }
inline void set_mesh_instance_visible(DirectMeshInstance &mi, bool visible) {
if (visible) {
mi.set_world(*_world);
} else {
mi.set_world(nullptr);
}
}
private:
Vector3i _position_in_voxels;
@ -76,6 +82,7 @@ private:
DirectMeshInstance _mesh_instance;
FixedArray<DirectMeshInstance, Cube::SIDE_COUNT> _transition_mesh_instances;
DirectStaticBody _static_body;
Ref<World> _world;
#ifdef VOXEL_DEBUG_LOD_MATERIALS
Ref<Material> _debug_material;

View File

@ -1068,6 +1068,7 @@ void VoxelLodTerrain::_process() {
// The block will be made visible and meshed only by LodOctree
block->set_visible(false);
block->set_parent_visible(is_visible());
block->set_world(get_world());
Ref<ShaderMaterial> shader_material = _material;
if (shader_material.is_valid() && block->get_shader_material().is_null()) {
@ -1254,7 +1255,7 @@ void VoxelLodTerrain::_process() {
mesh_data.compression_flags,
_material, nullptr);
block->set_transition_mesh(transition_mesh, dir, get_world());
block->set_transition_mesh(transition_mesh, dir);
}
}
}