Move mesh instance into a thin wrapper
parent
ed2db2b443
commit
332041751d
|
@ -1,4 +1,5 @@
|
|||
#include "voxel_block.h"
|
||||
#include <scene/resources/world.h>
|
||||
|
||||
// Helper
|
||||
VoxelBlock *VoxelBlock::create(Vector3i bpos, Ref<VoxelBuffer> buffer, unsigned int size, unsigned int p_lod_index) {
|
||||
|
@ -15,17 +16,10 @@ VoxelBlock *VoxelBlock::create(Vector3i bpos, Ref<VoxelBuffer> buffer, unsigned
|
|||
return block;
|
||||
}
|
||||
|
||||
VoxelBlock::VoxelBlock() :
|
||||
voxels(NULL) {
|
||||
VoxelBlock::VoxelBlock() {
|
||||
}
|
||||
|
||||
VoxelBlock::~VoxelBlock() {
|
||||
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) {
|
||||
|
@ -34,33 +28,27 @@ void VoxelBlock::set_mesh(Ref<Mesh> mesh, Ref<World> world) {
|
|||
// which is killing performance when LOD is used (i.e many meshes are in pool but hidden)
|
||||
// This needs investigation.
|
||||
|
||||
VisualServer &vs = *VisualServer::get_singleton();
|
||||
|
||||
if (mesh.is_valid()) {
|
||||
|
||||
if (_mesh_instance.is_valid() == false) {
|
||||
if (!_mesh_instance.is_valid()) {
|
||||
// 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());
|
||||
_mesh_instance.create();
|
||||
_mesh_instance.set_world(*world);
|
||||
}
|
||||
|
||||
vs.instance_set_base(_mesh_instance, mesh->get_rid());
|
||||
|
||||
Transform local_transform(Basis(), _position_in_voxels.to_vec3());
|
||||
vs.instance_set_transform(_mesh_instance, local_transform);
|
||||
_mesh_instance.set_mesh(mesh);
|
||||
_mesh_instance.set_transform(Transform(Basis(), _position_in_voxels.to_vec3()));
|
||||
// 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_instance.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
_mesh = mesh;
|
||||
++_mesh_update_count;
|
||||
|
||||
// if(_mesh_update_count > 1) {
|
||||
|
@ -69,7 +57,7 @@ void VoxelBlock::set_mesh(Ref<Mesh> mesh, Ref<World> world) {
|
|||
}
|
||||
|
||||
bool VoxelBlock::has_mesh() const {
|
||||
return _mesh.is_valid();
|
||||
return _mesh_instance.get_mesh().is_valid();
|
||||
}
|
||||
|
||||
void VoxelBlock::set_mesh_state(MeshState ms) {
|
||||
|
@ -88,24 +76,15 @@ bool VoxelBlock::has_been_meshed() const {
|
|||
return _has_been_meshed;
|
||||
}
|
||||
|
||||
void VoxelBlock::enter_world(World *world) {
|
||||
void VoxelBlock::set_world(World *world) {
|
||||
if (_mesh_instance.is_valid()) {
|
||||
VisualServer &vs = *VisualServer::get_singleton();
|
||||
vs.instance_set_scenario(_mesh_instance, world->get_scenario());
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelBlock::exit_world() {
|
||||
if (_mesh_instance.is_valid()) {
|
||||
VisualServer &vs = *VisualServer::get_singleton();
|
||||
vs.instance_set_scenario(_mesh_instance, RID());
|
||||
_mesh_instance.set_world(world);
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelBlock::set_visible(bool visible) {
|
||||
if (_mesh_instance.is_valid()) {
|
||||
VisualServer &vs = *VisualServer::get_singleton();
|
||||
vs.instance_set_visible(_mesh_instance, visible);
|
||||
_mesh_instance.set_visible(visible);
|
||||
}
|
||||
_visible = visible;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
#ifndef VOXEL_BLOCK_H
|
||||
#define VOXEL_BLOCK_H
|
||||
|
||||
#include "../util/direct_mesh_instance.h"
|
||||
#include "../voxel_buffer.h"
|
||||
|
||||
#include <scene/3d/mesh_instance.h>
|
||||
#include <scene/3d/physics_body.h>
|
||||
|
||||
// Internal structure holding a reference to mesh visuals, physics and a block of voxel data.
|
||||
class VoxelBlock {
|
||||
public:
|
||||
|
@ -34,8 +32,7 @@ public:
|
|||
void mark_been_meshed();
|
||||
bool has_been_meshed() const;
|
||||
|
||||
void enter_world(World *world);
|
||||
void exit_world();
|
||||
void set_world(World *world);
|
||||
void set_visible(bool visible);
|
||||
bool is_visible() const;
|
||||
|
||||
|
@ -48,11 +45,10 @@ private:
|
|||
|
||||
Vector3i _position_in_voxels;
|
||||
|
||||
Ref<Mesh> _mesh;
|
||||
RID _mesh_instance;
|
||||
DirectMeshInstance _mesh_instance;
|
||||
|
||||
int _mesh_update_count = 0;
|
||||
bool _visible = true;
|
||||
|
||||
MeshState _mesh_state = MESH_NEVER_UPDATED;
|
||||
|
||||
// The mesh might be null, but we don't know if it's actually empty or if it's loading.
|
||||
|
|
|
@ -368,18 +368,12 @@ Vector3 VoxelLodTerrain::voxel_to_block_position(Vector3 vpos, unsigned int lod_
|
|||
|
||||
void VoxelLodTerrain::_notification(int p_what) {
|
||||
|
||||
struct EnterWorldAction {
|
||||
struct SetWorldAction {
|
||||
World *world;
|
||||
EnterWorldAction(World *w) :
|
||||
SetWorldAction(World *w) :
|
||||
world(w) {}
|
||||
void operator()(VoxelBlock *block) {
|
||||
block->enter_world(world);
|
||||
}
|
||||
};
|
||||
|
||||
struct ExitWorldAction {
|
||||
void operator()(VoxelBlock *block) {
|
||||
block->exit_world();
|
||||
block->set_world(world);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -411,12 +405,12 @@ void VoxelLodTerrain::_notification(int p_what) {
|
|||
break;
|
||||
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
EnterWorldAction ewa(*get_world());
|
||||
SetWorldAction ewa(*get_world());
|
||||
for_all_blocks(ewa);
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
ExitWorldAction ewa;
|
||||
SetWorldAction ewa(nullptr);
|
||||
for_all_blocks(ewa);
|
||||
} break;
|
||||
|
||||
|
|
|
@ -621,18 +621,12 @@ void VoxelTerrain::make_area_dirty(Rect3i box) {
|
|||
|
||||
void VoxelTerrain::_notification(int p_what) {
|
||||
|
||||
struct EnterWorldAction {
|
||||
struct SetWorldAction {
|
||||
World *world;
|
||||
EnterWorldAction(World *w) :
|
||||
SetWorldAction(World *w) :
|
||||
world(w) {}
|
||||
void operator()(VoxelBlock *block) {
|
||||
block->enter_world(world);
|
||||
}
|
||||
};
|
||||
|
||||
struct ExitWorldAction {
|
||||
void operator()(VoxelBlock *block) {
|
||||
block->exit_world();
|
||||
block->set_world(world);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -665,12 +659,12 @@ void VoxelTerrain::_notification(int p_what) {
|
|||
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
ERR_FAIL_COND(_map.is_null());
|
||||
_map->for_all_blocks(EnterWorldAction(*get_world()));
|
||||
_map->for_all_blocks(SetWorldAction(*get_world()));
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_WORLD:
|
||||
ERR_FAIL_COND(_map.is_null());
|
||||
_map->for_all_blocks(ExitWorldAction());
|
||||
_map->for_all_blocks(SetWorldAction(nullptr));
|
||||
break;
|
||||
|
||||
case NOTIFICATION_VISIBILITY_CHANGED:
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
#include "direct_mesh_instance.h"
|
||||
#include <scene/resources/world.h>
|
||||
|
||||
DirectMeshInstance::DirectMeshInstance() {
|
||||
}
|
||||
|
||||
DirectMeshInstance::~DirectMeshInstance() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
bool DirectMeshInstance::is_valid() const {
|
||||
return _mesh_instance.is_valid();
|
||||
}
|
||||
|
||||
void DirectMeshInstance::create() {
|
||||
ERR_FAIL_COND(_mesh_instance.is_valid());
|
||||
VisualServer &vs = *VisualServer::get_singleton();
|
||||
_mesh_instance = vs.instance_create();
|
||||
vs.instance_set_visible(_mesh_instance, true); // TODO Is it needed?
|
||||
}
|
||||
|
||||
void DirectMeshInstance::destroy() {
|
||||
if (_mesh_instance.is_valid()) {
|
||||
VisualServer &vs = *VisualServer::get_singleton();
|
||||
vs.free(_mesh_instance);
|
||||
_mesh_instance = RID();
|
||||
_mesh.unref();
|
||||
}
|
||||
}
|
||||
|
||||
void DirectMeshInstance::set_world(World *world) {
|
||||
ERR_FAIL_COND(!_mesh_instance.is_valid());
|
||||
VisualServer &vs = *VisualServer::get_singleton();
|
||||
if (world != nullptr) {
|
||||
vs.instance_set_scenario(_mesh_instance, world->get_scenario());
|
||||
} else {
|
||||
vs.instance_set_scenario(_mesh_instance, RID());
|
||||
}
|
||||
}
|
||||
|
||||
void DirectMeshInstance::set_transform(Transform world_transform) {
|
||||
ERR_FAIL_COND(!_mesh_instance.is_valid());
|
||||
VisualServer &vs = *VisualServer::get_singleton();
|
||||
vs.instance_set_transform(_mesh_instance, world_transform);
|
||||
}
|
||||
|
||||
void DirectMeshInstance::set_mesh(Ref<Mesh> mesh) {
|
||||
ERR_FAIL_COND(!_mesh_instance.is_valid());
|
||||
VisualServer &vs = *VisualServer::get_singleton();
|
||||
if (mesh.is_valid()) {
|
||||
vs.instance_set_base(_mesh_instance, mesh->get_rid());
|
||||
} else {
|
||||
vs.instance_set_base(_mesh_instance, RID());
|
||||
}
|
||||
_mesh = mesh;
|
||||
}
|
||||
|
||||
void DirectMeshInstance::set_material_override(Ref<Material> material) {
|
||||
ERR_FAIL_COND(!_mesh_instance.is_valid());
|
||||
VisualServer &vs = *VisualServer::get_singleton();
|
||||
if (material.is_valid()) {
|
||||
vs.instance_geometry_set_material_override(_mesh_instance, material->get_rid());
|
||||
} else {
|
||||
vs.instance_geometry_set_material_override(_mesh_instance, RID());
|
||||
}
|
||||
}
|
||||
|
||||
void DirectMeshInstance::set_visible(bool visible) {
|
||||
ERR_FAIL_COND(!_mesh_instance.is_valid());
|
||||
VisualServer &vs = *VisualServer::get_singleton();
|
||||
vs.instance_set_visible(_mesh_instance, visible);
|
||||
}
|
||||
|
||||
Ref<Mesh> DirectMeshInstance::get_mesh() const {
|
||||
return _mesh;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef DIRECT_MESH_INSTANCE_H
|
||||
#define DIRECT_MESH_INSTANCE_H
|
||||
|
||||
#include <core/rid.h>
|
||||
#include <scene/resources/mesh.h>
|
||||
|
||||
class World;
|
||||
|
||||
// Thin wrapper around VisualServer mesh instance API
|
||||
class DirectMeshInstance {
|
||||
public:
|
||||
DirectMeshInstance();
|
||||
~DirectMeshInstance();
|
||||
|
||||
bool is_valid() const;
|
||||
void create();
|
||||
void destroy();
|
||||
void set_world(World *world);
|
||||
void set_transform(Transform world_transform);
|
||||
void set_mesh(Ref<Mesh> mesh);
|
||||
void set_material_override(Ref<Material> material);
|
||||
void set_visible(bool visible);
|
||||
|
||||
Ref<Mesh> get_mesh() const;
|
||||
|
||||
private:
|
||||
RID _mesh_instance;
|
||||
Ref<Mesh> _mesh;
|
||||
};
|
||||
|
||||
#endif // DIRECT_MESH_INSTANCE_H
|
Loading…
Reference in New Issue