Now Chunk has a vector of meshers, this simplifies for example liquid meshing, and this allows combining multiple meshers. Also the number of build phases is settable.

This commit is contained in:
Relintai 2020-01-13 00:39:55 +01:00
parent a67d0393ca
commit 104a307d55
2 changed files with 159 additions and 49 deletions

View File

@ -103,8 +103,12 @@ int VoxelChunk::get_lod_size() const {
void VoxelChunk::set_lod_size(const int lod_size) {
_lod_size = lod_size;
if (_mesher.is_valid()) {
_mesher->set_lod_size(_lod_size);
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
ERR_CONTINUE(!mesher.is_valid());
mesher->set_lod_size(_lod_size);
}
}
@ -114,8 +118,12 @@ float VoxelChunk::get_voxel_scale() const {
void VoxelChunk::set_voxel_scale(float value) {
_voxel_scale = value;
if (_mesher.is_valid()) {
_mesher->set_voxel_scale(_voxel_scale);
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
ERR_CONTINUE(!mesher.is_valid());
mesher->set_voxel_scale(_voxel_scale);
}
}
@ -126,11 +134,33 @@ void VoxelChunk::set_current_build_phase(int value) {
_current_build_phase = value;
}
Ref<VoxelMesher> VoxelChunk::get_mesher() const {
return _mesher;
int VoxelChunk::get_max_build_phase() {
return _max_build_phases;
}
void VoxelChunk::set_mesher(Ref<VoxelMesher> mesher) {
_mesher = mesher;
void VoxelChunk::set_max_build_phase(int value) {
_max_build_phases = value;
}
Ref<VoxelMesher> VoxelChunk::get_mesher(int index) const {
ERR_FAIL_INDEX_V(index, _meshers.size(), Ref<VoxelMesher>());
return _meshers.get(index);
}
void VoxelChunk::set_mesher(int index, Ref<VoxelMesher> mesher) {
ERR_FAIL_INDEX(index, _meshers.size());
_meshers.set(index, mesher);
}
void VoxelChunk::remove_mesher(int index) {
ERR_FAIL_INDEX(index, _meshers.size());
_meshers.remove(index);
}
void VoxelChunk::add_mesher(Ref<VoxelMesher> mesher) {
_meshers.push_back(mesher);
}
int VoxelChunk::get_mesher_count() {
return _meshers.size();
}
VoxelWorld *VoxelChunk::get_voxel_world() const {
@ -446,28 +476,44 @@ void VoxelChunk::clear_baked_lights() {
fill_channel(0, DEFAULT_CHANNEL_LIGHT_COLOR_B);
}
void VoxelChunk::create_mesher() {
call("_create_mesher");
void VoxelChunk::create_meshers() {
call("_create_meshers");
ERR_FAIL_COND(!_mesher.is_valid());
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
_mesher->set_lod_size(get_lod_size());
_mesher->set_voxel_scale(get_voxel_scale());
ERR_CONTINUE(!mesher.is_valid());
mesher->set_lod_size(get_lod_size());
mesher->set_voxel_scale(get_voxel_scale());
}
}
void VoxelChunk::_create_mesher() {
_mesher = Ref<VoxelMesher>(memnew(VoxelMesherCubic()));
void VoxelChunk::_create_meshers() {
add_mesher(Ref<VoxelMesher>(memnew(VoxelMesherCubic())));
}
void VoxelChunk::finalize_mesh() {
_mesher->set_library(_library);
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
ERR_CONTINUE(!mesher.is_valid());
mesher->set_library(_library);
}
if (_mesh_rid == RID()) {
allocate_main_mesh();
}
_mesher->set_material(get_library()->get_material());
get_mesher()->build_mesh(_mesh_rid);
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
ERR_CONTINUE(!mesher.is_valid());
mesher->set_material(get_library()->get_material());
mesher->build_mesh(_mesh_rid);
}
}
void VoxelChunk::build() {
@ -494,13 +540,18 @@ void VoxelChunk::_build_phase(int phase) {
case BUILD_PHASE_DONE:
return;
case BUILD_PHASE_SETUP: {
if (!_mesher.is_valid()) {
create_mesher();
if (_meshers.size() == 0) {
create_meshers();
}
_mesher->set_library(_library);
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
_mesher->reset();
ERR_CONTINUE(!mesher.is_valid());
mesher->set_library(_library);
mesher->reset();
}
next_phase();
@ -510,7 +561,13 @@ void VoxelChunk::_build_phase(int phase) {
if (has_method("_create_mesh")) {
call("_create_mesh");
} else {
_mesher->add_chunk(this);
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
ERR_CONTINUE(!mesher.is_valid());
mesher->add_chunk(this);
}
}
//finalize_mesh();
@ -529,7 +586,13 @@ void VoxelChunk::_build_phase(int phase) {
return;
}
case BUILD_PHASE_TERRARIN_MESH: {
_mesher->bake_colors(this);
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
ERR_CONTINUE(!mesher.is_valid());
mesher->bake_colors(this);
}
finalize_mesh();
@ -538,8 +601,13 @@ void VoxelChunk::_build_phase(int phase) {
return;
}
case BUILD_PHASE_PROP_MESH: {
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
_mesher->reset();
ERR_CONTINUE(!mesher.is_valid());
mesher->reset();
}
if (_props.size() > 0) {
process_props();
@ -558,7 +626,13 @@ void VoxelChunk::_build_phase(int phase) {
}
}
_mesher->reset();
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
ERR_CONTINUE(!mesher.is_valid());
mesher->reset();
}
next_phase();
@ -601,7 +675,7 @@ void VoxelChunk::next_phase() {
++_current_build_phase;
if (_current_build_phase >= BUILD_PHASE_MAX) {
if (_current_build_phase >= _max_build_phases) {
_current_build_phase = BUILD_PHASE_DONE;
_is_generating = false;
@ -644,7 +718,13 @@ void VoxelChunk::build_collider() {
create_colliders();
}
_mesher->build_collider(_shape_rid);
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
ERR_CONTINUE(!mesher.is_valid());
mesher->build_collider(_shape_rid);
}
}
void VoxelChunk::remove_colliders() {
@ -784,9 +864,15 @@ void VoxelChunk::process_props() {
call("_process_props");
_mesher->bake_colors(this);
_mesher->set_material(get_library()->get_material());
_mesher->build_mesh(_prop_mesh_rid);
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
ERR_CONTINUE(!mesher.is_valid());
mesher->bake_colors(this);
mesher->set_material(get_library()->get_material());
mesher->build_mesh(_prop_mesh_rid);
}
}
void VoxelChunk::build_prop_meshes() {
@ -794,9 +880,15 @@ void VoxelChunk::build_prop_meshes() {
allocate_prop_mesh();
}
_mesher->bake_colors(this);
_mesher->set_material(get_library()->get_material());
_mesher->build_mesh(_prop_mesh_rid);
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
ERR_CONTINUE(!mesher.is_valid());
mesher->bake_colors(this);
mesher->set_material(get_library()->get_material());
mesher->build_mesh(_prop_mesh_rid);
}
}
void VoxelChunk::allocate_main_mesh() {
@ -871,7 +963,13 @@ void VoxelChunk::build_prop_collider() {
allocate_prop_colliders();
}
_mesher->build_collider(_prop_shape_rid);
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
ERR_CONTINUE(!mesher.is_valid());
mesher->build_collider(_prop_shape_rid);
}
}
void VoxelChunk::free_prop_colliders() {
if (_prop_body_rid != RID()) {
@ -1081,6 +1179,7 @@ VoxelChunk::VoxelChunk() {
_create_collider = true;
_bake_lights = true;
_current_build_phase = BUILD_PHASE_DONE;
_max_build_phases = BUILD_PHASE_MAX;
_voxel_scale = 1;
_lod_size = 1;
@ -1105,9 +1204,7 @@ VoxelChunk::~VoxelChunk() {
_voxel_lights.clear();
if (_mesher.is_valid()) {
_mesher.unref();
}
_meshers.clear();
if (_library.is_valid()) {
_library.unref();
@ -1142,11 +1239,11 @@ void VoxelChunk::_bind_methods() {
ADD_SIGNAL(MethodInfo("mesh_generation_finished", PropertyInfo(Variant::OBJECT, "chunk", PROPERTY_HINT_RESOURCE_TYPE, "VoxelChunk")));
BIND_VMETHOD(MethodInfo("_create_mesh"));
BIND_VMETHOD(MethodInfo("_create_mesher"));
BIND_VMETHOD(MethodInfo("_create_meshers"));
BIND_VMETHOD(MethodInfo("_prop_added", PropertyInfo(Variant::OBJECT, "prop", PROPERTY_HINT_RESOURCE_TYPE, "VoxelChunkPropData")));
ClassDB::bind_method(D_METHOD("_create_mesher"), &VoxelChunk::_create_mesher);
ClassDB::bind_method(D_METHOD("_create_meshers"), &VoxelChunk::_create_meshers);
ClassDB::bind_method(D_METHOD("get_is_generating"), &VoxelChunk::get_is_generating);
ClassDB::bind_method(D_METHOD("set_is_generating", "value"), &VoxelChunk::set_is_generating);
@ -1217,6 +1314,10 @@ void VoxelChunk::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_current_build_phase", "value"), &VoxelChunk::set_current_build_phase);
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_build_phase"), "set_current_build_phase", "get_current_build_phase");
ClassDB::bind_method(D_METHOD("get_max_build_phase"), &VoxelChunk::get_max_build_phase);
ClassDB::bind_method(D_METHOD("set_max_build_phase", "value"), &VoxelChunk::set_max_build_phase);
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_build_phase"), "set_max_build_phase", "get_max_build_phase");
ADD_GROUP("Meshing", "meshing");
ClassDB::bind_method(D_METHOD("meshing_get_create_collider"), &VoxelChunk::get_create_collider);
@ -1229,9 +1330,11 @@ void VoxelChunk::_bind_methods() {
ADD_GROUP("Settings", "setting");
ClassDB::bind_method(D_METHOD("get_mesher"), &VoxelChunk::get_mesher);
ClassDB::bind_method(D_METHOD("set_mesher", "Mesher"), &VoxelChunk::set_mesher);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesher", PROPERTY_HINT_RESOURCE_TYPE, "VoxelMesher"), "set_mesher", "get_mesher");
ClassDB::bind_method(D_METHOD("get_mesher", "index"), &VoxelChunk::get_mesher);
ClassDB::bind_method(D_METHOD("set_mesher", "index", "mesher"), &VoxelChunk::set_mesher);
ClassDB::bind_method(D_METHOD("remove_mesher", "index"), &VoxelChunk::remove_mesher);
ClassDB::bind_method(D_METHOD("add_mesher", "mesher"), &VoxelChunk::add_mesher);
ClassDB::bind_method(D_METHOD("get_mesher_count"), &VoxelChunk::get_mesher_count);
ClassDB::bind_method(D_METHOD("get_voxel_world"), &VoxelChunk::get_voxel_world);
ClassDB::bind_method(D_METHOD("set_voxel_world", "world"), &VoxelChunk::set_voxel_world_bind);
@ -1337,7 +1440,7 @@ void VoxelChunk::_bind_methods() {
ClassDB::bind_method(D_METHOD("allocate_clutter_mesh"), &VoxelChunk::allocate_clutter_mesh);
ClassDB::bind_method(D_METHOD("free_clutter_mesh"), &VoxelChunk::free_clutter_mesh);
ClassDB::bind_method(D_METHOD("create_mesher"), &VoxelChunk::create_mesher);
ClassDB::bind_method(D_METHOD("create_meshers"), &VoxelChunk::create_meshers);
ClassDB::bind_method(D_METHOD("create_debug_immediate_geometry"), &VoxelChunk::create_debug_immediate_geometry);
ClassDB::bind_method(D_METHOD("free_debug_immediate_geometry"), &VoxelChunk::free_debug_immediate_geometry);

View File

@ -127,8 +127,14 @@ public:
int get_current_build_phase();
void set_current_build_phase(int value);
Ref<VoxelMesher> get_mesher() const;
void set_mesher(Ref<VoxelMesher> mesher);
int get_max_build_phase();
void set_max_build_phase(int value);
Ref<VoxelMesher> get_mesher(int index) const;
void set_mesher(int index, Ref<VoxelMesher> mesher);
void remove_mesher(int index);
void add_mesher(Ref<VoxelMesher> mesher);
int get_mesher_count();
VoxelWorld *get_voxel_world() const;
void set_voxel_world(VoxelWorld *world);
@ -185,8 +191,8 @@ public:
void clear_baked_lights();
//Meshing
void create_mesher();
void _create_mesher();
void create_meshers();
void _create_meshers();
void finalize_mesh();
@ -274,6 +280,7 @@ protected:
int _state;
int _current_build_phase;
int _max_build_phases;
bool _enabled;
VoxelWorld *_voxel_world;
@ -302,7 +309,7 @@ protected:
NodePath _library_path;
Ref<VoxelmanLibrary> _library;
Ref<VoxelMesher> _mesher;
Vector<Ref<VoxelMesher> > _meshers;
//voxel mesh
RID _mesh_rid;