Renamed Voxel => VoxelBlockyModel, VoxelLibrary => VoxelBlockyLibrary

This commit is contained in:
Marc Gilleron 2022-01-09 23:23:59 +00:00
parent f859ec1922
commit f8b8b27ff2
15 changed files with 165 additions and 160 deletions

View File

@ -38,6 +38,8 @@ Godot 4 is required from this version.
- Some functions now take `Vector3i` instead of `Vector3`. If you used to send `Vector3` without `floor()` or `round()`, it can have side-effects in negative coordinates. - Some functions now take `Vector3i` instead of `Vector3`. If you used to send `Vector3` without `floor()` or `round()`, it can have side-effects in negative coordinates.
- `VoxelLodTerrain`: `set_process_mode` and `get_process_mode` were renamed `set_process_callback` and `get_process_callback` (due to a name conflict) - `VoxelLodTerrain`: `set_process_mode` and `get_process_mode` were renamed `set_process_callback` and `get_process_callback` (due to a name conflict)
- `VoxelMesherTransvoxel`: Shader API: The data in `COLOR` and `UV` was moved respectively to `CUSTOM0` and `CUSTOM1` (old attributes no longer work for this use case) - `VoxelMesherTransvoxel`: Shader API: The data in `COLOR` and `UV` was moved respectively to `CUSTOM0` and `CUSTOM1` (old attributes no longer work for this use case)
- `Voxel` was renamed `VoxelBlockyModel`
- `VoxelLibrary` was renamed `VoxelBlockyLibrary`
- Known issues - Known issues
- Some nodes and resources no longer start with predefined properties due to a warning introduced in Godot4 when properties are resources. - Some nodes and resources no longer start with predefined properties due to a warning introduced in Godot4 when properties are resources.

View File

@ -45,7 +45,7 @@ Ref<VoxelRaycastResult> VoxelToolTerrain::raycast(
struct RaycastPredicateBlocky { struct RaycastPredicateBlocky {
const VoxelDataMap &map; const VoxelDataMap &map;
const VoxelLibrary &library; const VoxelBlockyLibrary &library;
const uint32_t collision_mask; const uint32_t collision_mask;
bool operator()(const Vector3i pos) const { bool operator()(const Vector3i pos) const {
@ -55,7 +55,7 @@ Ref<VoxelRaycastResult> VoxelToolTerrain::raycast(
return false; return false;
} }
const Voxel &voxel = library.get_voxel_const(v); const VoxelBlockyModel &voxel = library.get_voxel_const(v);
if (voxel.is_empty()) { if (voxel.is_empty()) {
return false; return false;
} }
@ -92,7 +92,7 @@ Ref<VoxelRaycastResult> VoxelToolTerrain::raycast(
const float max_distance = p_max_distance / to_world_scale; const float max_distance = p_max_distance / to_world_scale;
if (try_get_as(_terrain->get_mesher(), mesher_blocky)) { if (try_get_as(_terrain->get_mesher(), mesher_blocky)) {
Ref<VoxelLibrary> library_ref = mesher_blocky->get_library(); Ref<VoxelBlockyLibrary> library_ref = mesher_blocky->get_library();
if (library_ref.is_null()) { if (library_ref.is_null()) {
return res; return res;
} }
@ -222,7 +222,7 @@ Variant VoxelToolTerrain::get_voxel_metadata(Vector3i pos) const {
return block->get_voxels_const().get_voxel_metadata(map.to_local(pos)); return block->get_voxels_const().get_voxel_metadata(map.to_local(pos));
} }
void VoxelToolTerrain::run_blocky_random_tick_static(VoxelDataMap &map, Box3i voxel_box, const VoxelLibrary &lib, void VoxelToolTerrain::run_blocky_random_tick_static(VoxelDataMap &map, Box3i voxel_box, const VoxelBlockyLibrary &lib,
int voxel_count, int batch_count, void *callback_data, bool (*callback)(void *, Vector3i, int64_t)) { int voxel_count, int batch_count, void *callback_data, bool (*callback)(void *, Vector3i, int64_t)) {
ERR_FAIL_COND(batch_count <= 0); ERR_FAIL_COND(batch_count <= 0);
ERR_FAIL_COND(voxel_count < 0); ERR_FAIL_COND(voxel_count < 0);
@ -273,7 +273,7 @@ void VoxelToolTerrain::run_blocky_random_tick_static(VoxelDataMap &map, Box3i vo
if (voxels.get_channel_compression(channel) == VoxelBufferInternal::COMPRESSION_UNIFORM) { if (voxels.get_channel_compression(channel) == VoxelBufferInternal::COMPRESSION_UNIFORM) {
const uint64_t v = voxels.get_voxel(0, 0, 0, channel); const uint64_t v = voxels.get_voxel(0, 0, 0, channel);
if (lib.has_voxel(v)) { if (lib.has_voxel(v)) {
const Voxel &vt = lib.get_voxel_const(v); const VoxelBlockyModel &vt = lib.get_voxel_const(v);
if (!vt.is_random_tickable()) { if (!vt.is_random_tickable()) {
// Skip whole block // Skip whole block
continue; continue;
@ -305,7 +305,7 @@ void VoxelToolTerrain::run_blocky_random_tick_static(VoxelDataMap &map, Box3i vo
const Pick pick = picks[i]; const Pick pick = picks[i];
if (lib.has_voxel(pick.value)) { if (lib.has_voxel(pick.value)) {
const Voxel &vt = lib.get_voxel_const(pick.value); const VoxelBlockyModel &vt = lib.get_voxel_const(pick.value);
if (vt.is_random_tickable()) { if (vt.is_random_tickable()) {
ERR_FAIL_COND(!callback(callback_data, pick.rpos + block_origin, pick.value)); ERR_FAIL_COND(!callback(callback_data, pick.rpos + block_origin, pick.value));
@ -340,7 +340,7 @@ void VoxelToolTerrain::run_blocky_random_tick(
}; };
CallbackData cb_self{ callback }; CallbackData cb_self{ callback };
const VoxelLibrary &lib = **_terrain->get_voxel_library(); const VoxelBlockyLibrary &lib = **_terrain->get_voxel_library();
VoxelDataMap &map = _terrain->get_storage(); VoxelDataMap &map = _terrain->get_storage();
const Box3i voxel_box(Vector3iUtil::from_floored(voxel_area.position), Vector3iUtil::from_floored(voxel_area.size)); const Box3i voxel_box(Vector3iUtil::from_floored(voxel_area.position), Vector3iUtil::from_floored(voxel_area.size));

View File

@ -6,7 +6,7 @@
namespace zylann::voxel { namespace zylann::voxel {
class VoxelTerrain; class VoxelTerrain;
class VoxelLibrary; class VoxelBlockyLibrary;
class VoxelDataMap; class VoxelDataMap;
class VoxelToolTerrain : public VoxelTool { class VoxelToolTerrain : public VoxelTool {
@ -35,7 +35,7 @@ public:
// For easier unit testing (the regular one needs a terrain setup etc, harder to test atm) // For easier unit testing (the regular one needs a terrain setup etc, harder to test atm)
// The `_static` suffix is because it otherwise conflicts with the non-static method when registering the class // The `_static` suffix is because it otherwise conflicts with the non-static method when registering the class
static void run_blocky_random_tick_static(VoxelDataMap &map, Box3i voxel_box, const VoxelLibrary &lib, static void run_blocky_random_tick_static(VoxelDataMap &map, Box3i voxel_box, const VoxelBlockyLibrary &lib,
int voxel_count, int batch_count, void *callback_data, bool (*callback)(void *, Vector3i, int64_t)); int voxel_count, int batch_count, void *callback_data, bool (*callback)(void *, Vector3i, int64_t));
void for_each_voxel_metadata_in_area(AABB voxel_area, const Callable &callback); void for_each_voxel_metadata_in_area(AABB voxel_area, const Callable &callback);

View File

@ -1,4 +1,4 @@
#include "voxel_library.h" #include "voxel_blocky_library.h"
#include "../../util/macros.h" #include "../../util/macros.h"
#include <core/math/geometry_2d.h> #include <core/math/geometry_2d.h>
@ -8,15 +8,15 @@
namespace zylann::voxel { namespace zylann::voxel {
VoxelLibrary::VoxelLibrary() {} VoxelBlockyLibrary::VoxelBlockyLibrary() {}
VoxelLibrary::~VoxelLibrary() {} VoxelBlockyLibrary::~VoxelBlockyLibrary() {}
unsigned int VoxelLibrary::get_voxel_count() const { unsigned int VoxelBlockyLibrary::get_voxel_count() const {
return _voxel_types.size(); return _voxel_types.size();
} }
void VoxelLibrary::set_voxel_count(unsigned int type_count) { void VoxelBlockyLibrary::set_voxel_count(unsigned int type_count) {
ERR_FAIL_COND(type_count > MAX_VOXEL_TYPES); ERR_FAIL_COND(type_count > MAX_VOXEL_TYPES);
if (type_count == _voxel_types.size()) { if (type_count == _voxel_types.size()) {
return; return;
@ -27,9 +27,9 @@ void VoxelLibrary::set_voxel_count(unsigned int type_count) {
_needs_baking = true; _needs_baking = true;
} }
int VoxelLibrary::get_voxel_index_from_name(StringName name) const { int VoxelBlockyLibrary::get_voxel_index_from_name(StringName name) const {
for (size_t i = 0; i < _voxel_types.size(); ++i) { for (size_t i = 0; i < _voxel_types.size(); ++i) {
const Ref<Voxel> &v = _voxel_types[i]; const Ref<VoxelBlockyModel> &v = _voxel_types[i];
if (v.is_null()) { if (v.is_null()) {
continue; continue;
} }
@ -40,20 +40,20 @@ int VoxelLibrary::get_voxel_index_from_name(StringName name) const {
return -1; return -1;
} }
void VoxelLibrary::load_default() { void VoxelBlockyLibrary::load_default() {
set_voxel_count(2); set_voxel_count(2);
Ref<Voxel> air = create_voxel(0, "air"); Ref<VoxelBlockyModel> air = create_voxel(0, "air");
air->set_transparent(true); air->set_transparent(true);
Ref<Voxel> solid = create_voxel(1, "solid"); Ref<VoxelBlockyModel> solid = create_voxel(1, "solid");
solid->set_transparent(false); solid->set_transparent(false);
solid->set_geometry_type(Voxel::GEOMETRY_CUBE); solid->set_geometry_type(VoxelBlockyModel::GEOMETRY_CUBE);
} }
// TODO Add a way to add voxels // TODO Add a way to add voxels
bool VoxelLibrary::_set(const StringName &p_name, const Variant &p_value) { bool VoxelBlockyLibrary::_set(const StringName &p_name, const Variant &p_value) {
// if(p_name == "voxels/max") { // if(p_name == "voxels/max") {
// int v = p_value; // int v = p_value;
@ -73,7 +73,7 @@ bool VoxelLibrary::_set(const StringName &p_name, const Variant &p_value) {
return false; return false;
} }
bool VoxelLibrary::_get(const StringName &p_name, Variant &r_ret) const { bool VoxelBlockyLibrary::_get(const StringName &p_name, Variant &r_ret) const {
// if(p_name == "voxels/max") { // if(p_name == "voxels/max") {
// r_ret = _max_count; // r_ret = _max_count;
@ -91,33 +91,33 @@ bool VoxelLibrary::_get(const StringName &p_name, Variant &r_ret) const {
return false; return false;
} }
void VoxelLibrary::_get_property_list(List<PropertyInfo> *p_list) const { void VoxelBlockyLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
for (unsigned int i = 0; i < _voxel_types.size(); ++i) { for (unsigned int i = 0; i < _voxel_types.size(); ++i) {
p_list->push_back(PropertyInfo(Variant::OBJECT, "voxels/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "Voxel")); p_list->push_back(PropertyInfo(Variant::OBJECT, "voxels/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "Voxel"));
} }
} }
void VoxelLibrary::set_atlas_size(int s) { void VoxelBlockyLibrary::set_atlas_size(int s) {
ERR_FAIL_COND(s <= 0); ERR_FAIL_COND(s <= 0);
_atlas_size = s; _atlas_size = s;
_needs_baking = true; _needs_baking = true;
} }
void VoxelLibrary::set_bake_tangents(bool bt) { void VoxelBlockyLibrary::set_bake_tangents(bool bt) {
_bake_tangents = bt; _bake_tangents = bt;
_needs_baking = true; _needs_baking = true;
} }
Ref<Voxel> VoxelLibrary::create_voxel(unsigned int id, String name) { Ref<VoxelBlockyModel> VoxelBlockyLibrary::create_voxel(unsigned int id, String name) {
ERR_FAIL_COND_V(id >= _voxel_types.size(), Ref<Voxel>()); ERR_FAIL_COND_V(id >= _voxel_types.size(), Ref<VoxelBlockyModel>());
Ref<Voxel> voxel(memnew(Voxel)); Ref<VoxelBlockyModel> voxel(memnew(VoxelBlockyModel));
voxel->set_id(id); voxel->set_id(id);
voxel->set_voxel_name(name); voxel->set_voxel_name(name);
_voxel_types[id] = voxel; _voxel_types[id] = voxel;
return voxel; return voxel;
} }
void VoxelLibrary::set_voxel(unsigned int idx, Ref<Voxel> voxel) { void VoxelBlockyLibrary::set_voxel(unsigned int idx, Ref<VoxelBlockyModel> voxel) {
ERR_FAIL_INDEX(idx, MAX_VOXEL_TYPES); ERR_FAIL_INDEX(idx, MAX_VOXEL_TYPES);
if (idx >= _voxel_types.size()) { if (idx >= _voxel_types.size()) {
@ -161,7 +161,7 @@ static void rasterize_triangle_barycentric(Vector2 a, Vector2 b, Vector2 c, F ou
} }
} }
void VoxelLibrary::bake() { void VoxelBlockyLibrary::bake() {
RWLockWrite lock(_baked_data_rw_lock); RWLockWrite lock(_baked_data_rw_lock);
const uint64_t time_before = Time::get_singleton()->get_ticks_usec(); const uint64_t time_before = Time::get_singleton()->get_ticks_usec();
@ -170,7 +170,7 @@ void VoxelLibrary::bake() {
_baked_data.models.resize(_voxel_types.size()); _baked_data.models.resize(_voxel_types.size());
for (size_t i = 0; i < _voxel_types.size(); ++i) { for (size_t i = 0; i < _voxel_types.size(); ++i) {
Ref<Voxel> config = _voxel_types[i]; Ref<VoxelBlockyModel> config = _voxel_types[i];
if (config.is_valid()) { if (config.is_valid()) {
_voxel_types[i]->bake(_baked_data.models[i], _atlas_size, _bake_tangents); _voxel_types[i]->bake(_baked_data.models[i], _atlas_size, _bake_tangents);
} else { } else {
@ -184,7 +184,7 @@ void VoxelLibrary::bake() {
PRINT_VERBOSE(String("Took {0} us to bake VoxelLibrary").format(varray(time_spent))); PRINT_VERBOSE(String("Took {0} us to bake VoxelLibrary").format(varray(time_spent)));
} }
void VoxelLibrary::generate_side_culling_matrix() { void VoxelBlockyLibrary::generate_side_culling_matrix() {
// When two blocky voxels are next to each other, they share a side. // When two blocky voxels are next to each other, they share a side.
// Geometry of either side can be culled away if covered by the other, // Geometry of either side can be culled away if covered by the other,
// but it's very expensive to do a full polygon check when we build the mesh. // but it's very expensive to do a full polygon check when we build the mesh.
@ -216,7 +216,7 @@ void VoxelLibrary::generate_side_culling_matrix() {
continue; continue;
} }
Voxel::BakedData &model_data = _baked_data.models[type_id]; VoxelBlockyModel::BakedData &model_data = _baked_data.models[type_id];
model_data.contributes_to_ao = true; model_data.contributes_to_ao = true;
for (uint16_t side = 0; side < Cube::SIDE_COUNT; ++side) { for (uint16_t side = 0; side < Cube::SIDE_COUNT; ++side) {
@ -394,23 +394,34 @@ void VoxelLibrary::generate_side_culling_matrix() {
print_line("");*/ print_line("");*/
} }
void VoxelLibrary::_bind_methods() { Ref<VoxelBlockyModel> VoxelBlockyLibrary::_b_get_voxel(unsigned int id) {
ClassDB::bind_method(D_METHOD("create_voxel", "id", "name"), &VoxelLibrary::create_voxel); ERR_FAIL_COND_V(id >= _voxel_types.size(), Ref<VoxelBlockyModel>());
ClassDB::bind_method(D_METHOD("get_voxel", "id"), &VoxelLibrary::_b_get_voxel); return _voxel_types[id];
}
ClassDB::bind_method(D_METHOD("set_atlas_size", "square_size"), &VoxelLibrary::set_atlas_size); Ref<VoxelBlockyModel> VoxelBlockyLibrary::_b_get_voxel_by_name(StringName name) {
ClassDB::bind_method(D_METHOD("get_atlas_size"), &VoxelLibrary::get_atlas_size); int id = get_voxel_index_from_name(name);
ERR_FAIL_COND_V(id == -1, Ref<VoxelBlockyModel>());
return _voxel_types[id];
}
ClassDB::bind_method(D_METHOD("set_voxel_count", "count"), &VoxelLibrary::set_voxel_count); void VoxelBlockyLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_voxel_count"), &VoxelLibrary::get_voxel_count); ClassDB::bind_method(D_METHOD("create_voxel", "id", "name"), &VoxelBlockyLibrary::create_voxel);
ClassDB::bind_method(D_METHOD("get_voxel", "id"), &VoxelBlockyLibrary::_b_get_voxel);
ClassDB::bind_method(D_METHOD("get_bake_tangents"), &VoxelLibrary::get_bake_tangents); ClassDB::bind_method(D_METHOD("set_atlas_size", "square_size"), &VoxelBlockyLibrary::set_atlas_size);
ClassDB::bind_method(D_METHOD("set_bake_tangents", "bake_tangents"), &VoxelLibrary::set_bake_tangents); ClassDB::bind_method(D_METHOD("get_atlas_size"), &VoxelBlockyLibrary::get_atlas_size);
ClassDB::bind_method(D_METHOD("get_voxel_index_from_name", "name"), &VoxelLibrary::get_voxel_index_from_name); ClassDB::bind_method(D_METHOD("set_voxel_count", "count"), &VoxelBlockyLibrary::set_voxel_count);
ClassDB::bind_method(D_METHOD("get_voxel_by_name", "name"), &VoxelLibrary::_b_get_voxel_by_name); ClassDB::bind_method(D_METHOD("get_voxel_count"), &VoxelBlockyLibrary::get_voxel_count);
ClassDB::bind_method(D_METHOD("bake"), &VoxelLibrary::bake); ClassDB::bind_method(D_METHOD("get_bake_tangents"), &VoxelBlockyLibrary::get_bake_tangents);
ClassDB::bind_method(D_METHOD("set_bake_tangents", "bake_tangents"), &VoxelBlockyLibrary::set_bake_tangents);
ClassDB::bind_method(D_METHOD("get_voxel_index_from_name", "name"), &VoxelBlockyLibrary::get_voxel_index_from_name);
ClassDB::bind_method(D_METHOD("get_voxel_by_name", "name"), &VoxelBlockyLibrary::_b_get_voxel_by_name);
ClassDB::bind_method(D_METHOD("bake"), &VoxelBlockyLibrary::bake);
ADD_PROPERTY(PropertyInfo(Variant::INT, "atlas_size"), "set_atlas_size", "get_atlas_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "atlas_size"), "set_atlas_size", "get_atlas_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "voxel_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), ADD_PROPERTY(PropertyInfo(Variant::INT, "voxel_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR),
@ -420,15 +431,4 @@ void VoxelLibrary::_bind_methods() {
BIND_CONSTANT(MAX_VOXEL_TYPES); BIND_CONSTANT(MAX_VOXEL_TYPES);
} }
Ref<Voxel> VoxelLibrary::_b_get_voxel(unsigned int id) {
ERR_FAIL_COND_V(id >= _voxel_types.size(), Ref<Voxel>());
return _voxel_types[id];
}
Ref<Voxel> VoxelLibrary::_b_get_voxel_by_name(StringName name) {
int id = get_voxel_index_from_name(name);
ERR_FAIL_COND_V(id == -1, Ref<Voxel>());
return _voxel_types[id];
}
} // namespace zylann::voxel } // namespace zylann::voxel

View File

@ -2,7 +2,7 @@
#define VOXEL_LIBRARY_H #define VOXEL_LIBRARY_H
#include "../../util/dynamic_bitset.h" #include "../../util/dynamic_bitset.h"
#include "voxel.h" #include "voxel_blocky_model.h"
#include <core/object/ref_counted.h> #include <core/object/ref_counted.h>
namespace zylann::voxel { namespace zylann::voxel {
@ -10,8 +10,8 @@ namespace zylann::voxel {
// TODO Rename VoxelBlockyLibrary // TODO Rename VoxelBlockyLibrary
// Stores a list of models that can be used with VoxelMesherBlocky // Stores a list of models that can be used with VoxelMesherBlocky
class VoxelLibrary : public Resource { class VoxelBlockyLibrary : public Resource {
GDCLASS(VoxelLibrary, Resource) GDCLASS(VoxelBlockyLibrary, Resource)
public: public:
// Limit based on maximum supported by VoxelMesherBlocky // Limit based on maximum supported by VoxelMesherBlocky
@ -24,7 +24,7 @@ public:
DynamicBitset side_pattern_culling; DynamicBitset side_pattern_culling;
unsigned int side_pattern_count = 0; unsigned int side_pattern_count = 0;
// Lots of data can get moved but it's only on load. // Lots of data can get moved but it's only on load.
std::vector<Voxel::BakedData> models; std::vector<VoxelBlockyModel::BakedData> models;
inline bool has_model(uint32_t i) const { inline bool has_model(uint32_t i) const {
return i < models.size(); return i < models.size();
@ -39,8 +39,8 @@ public:
} }
}; };
VoxelLibrary(); VoxelBlockyLibrary();
~VoxelLibrary(); ~VoxelBlockyLibrary();
int get_atlas_size() const { int get_atlas_size() const {
return _atlas_size; return _atlas_size;
@ -48,7 +48,7 @@ public:
void set_atlas_size(int s); void set_atlas_size(int s);
// Use this factory rather than creating voxels from scratch // Use this factory rather than creating voxels from scratch
Ref<Voxel> create_voxel(unsigned int id, String name); Ref<VoxelBlockyModel> create_voxel(unsigned int id, String name);
unsigned int get_voxel_count() const; unsigned int get_voxel_count() const;
void set_voxel_count(unsigned int type_count); void set_voxel_count(unsigned int type_count);
@ -71,7 +71,7 @@ public:
return id < _voxel_types.size() && _voxel_types[id].is_valid(); return id < _voxel_types.size() && _voxel_types[id].is_valid();
} }
_FORCE_INLINE_ const Voxel &get_voxel_const(unsigned int id) const { _FORCE_INLINE_ const VoxelBlockyModel &get_voxel_const(unsigned int id) const {
return **_voxel_types[id]; return **_voxel_types[id];
} }
@ -83,7 +83,7 @@ public:
} }
private: private:
void set_voxel(unsigned int id, Ref<Voxel> voxel); void set_voxel(unsigned int id, Ref<VoxelBlockyModel> voxel);
void generate_side_culling_matrix(); void generate_side_culling_matrix();
@ -91,15 +91,15 @@ private:
bool _get(const StringName &p_name, Variant &r_ret) const; bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const; void _get_property_list(List<PropertyInfo> *p_list) const;
Ref<Voxel> _b_get_voxel(unsigned int id); Ref<VoxelBlockyModel> _b_get_voxel(unsigned int id);
Ref<Voxel> _b_get_voxel_by_name(StringName name); Ref<VoxelBlockyModel> _b_get_voxel_by_name(StringName name);
static void _bind_methods(); static void _bind_methods();
private: private:
// There can be null entries. A vector is used because there should be no more than 65,536 items, // There can be null entries. A vector is used because there should be no more than 65,536 items,
// and in practice the intented use case rarely goes over a few hundreds // and in practice the intented use case rarely goes over a few hundreds
std::vector<Ref<Voxel>> _voxel_types; std::vector<Ref<VoxelBlockyModel>> _voxel_types;
int _atlas_size = 16; int _atlas_size = 16;
bool _needs_baking = true; bool _needs_baking = true;
bool _bake_tangents = true; bool _bake_tangents = true;

View File

@ -1,11 +1,11 @@
#include "voxel.h" #include "voxel_blocky_model.h"
#include "../../util/macros.h" #include "../../util/macros.h"
#include "voxel_library.h" #include "voxel_blocky_library.h"
#include "voxel_mesher_blocky.h" // TODO Only required because of MAX_MATERIALS... could be enough inverting that dependency #include "voxel_mesher_blocky.h" // TODO Only required because of MAX_MATERIALS... could be enough inverting that dependency
namespace zylann::voxel { namespace zylann::voxel {
Voxel::Voxel() : VoxelBlockyModel::VoxelBlockyModel() :
_id(-1), _material_id(0), _transparency_index(0), _color(1.f, 1.f, 1.f), _geometry_type(GEOMETRY_NONE) {} _id(-1), _material_id(0), _transparency_index(0), _color(1.f, 1.f, 1.f), _geometry_type(GEOMETRY_NONE) {}
static Cube::Side name_to_side(const String &s) { static Cube::Side name_to_side(const String &s) {
@ -30,7 +30,7 @@ static Cube::Side name_to_side(const String &s) {
return Cube::SIDE_COUNT; // Invalid return Cube::SIDE_COUNT; // Invalid
} }
bool Voxel::_set(const StringName &p_name, const Variant &p_value) { bool VoxelBlockyModel::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name; String name = p_name;
// TODO Eventualy these could be Rect2 for maximum flexibility? // TODO Eventualy these could be Rect2 for maximum flexibility?
@ -47,7 +47,7 @@ bool Voxel::_set(const StringName &p_name, const Variant &p_value) {
return false; return false;
} }
bool Voxel::_get(const StringName &p_name, Variant &r_ret) const { bool VoxelBlockyModel::_get(const StringName &p_name, Variant &r_ret) const {
String name = p_name; String name = p_name;
if (name.begins_with("cube_tiles/")) { if (name.begins_with("cube_tiles/")) {
@ -62,7 +62,7 @@ bool Voxel::_get(const StringName &p_name, Variant &r_ret) const {
return false; return false;
} }
void Voxel::_get_property_list(List<PropertyInfo> *p_list) const { void VoxelBlockyModel::_get_property_list(List<PropertyInfo> *p_list) const {
if (_geometry_type == GEOMETRY_CUBE) { if (_geometry_type == GEOMETRY_CUBE) {
p_list->push_back(PropertyInfo(Variant::FLOAT, "cube_geometry/padding_y")); p_list->push_back(PropertyInfo(Variant::FLOAT, "cube_geometry/padding_y"));
p_list->push_back(PropertyInfo(Variant::VECTOR2, "cube_tiles/left")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "cube_tiles/left"));
@ -74,27 +74,27 @@ void Voxel::_get_property_list(List<PropertyInfo> *p_list) const {
} }
} }
void Voxel::set_voxel_name(String name) { void VoxelBlockyModel::set_voxel_name(String name) {
_name = name; _name = name;
} }
void Voxel::set_id(int id) { void VoxelBlockyModel::set_id(int id) {
ERR_FAIL_COND(id < 0 || (unsigned int)id >= VoxelLibrary::MAX_VOXEL_TYPES); ERR_FAIL_COND(id < 0 || (unsigned int)id >= VoxelBlockyLibrary::MAX_VOXEL_TYPES);
// Cannot modify ID after creation // Cannot modify ID after creation
ERR_FAIL_COND_MSG(_id != -1, "ID cannot be modified after being added to a library"); ERR_FAIL_COND_MSG(_id != -1, "ID cannot be modified after being added to a library");
_id = id; _id = id;
} }
void Voxel::set_color(Color color) { void VoxelBlockyModel::set_color(Color color) {
_color = color; _color = color;
} }
void Voxel::set_material_id(unsigned int id) { void VoxelBlockyModel::set_material_id(unsigned int id) {
ERR_FAIL_COND(id >= VoxelMesherBlocky::MAX_MATERIALS); ERR_FAIL_COND(id >= VoxelMesherBlocky::MAX_MATERIALS);
_material_id = id; _material_id = id;
} }
void Voxel::set_transparent(bool t) { void VoxelBlockyModel::set_transparent(bool t) {
if (t) { if (t) {
if (_transparency_index == 0) { if (_transparency_index == 0) {
_transparency_index = 1; _transparency_index = 1;
@ -104,11 +104,11 @@ void Voxel::set_transparent(bool t) {
} }
} }
void Voxel::set_transparency_index(int i) { void VoxelBlockyModel::set_transparency_index(int i) {
_transparency_index = math::clamp(i, 0, 255); _transparency_index = math::clamp(i, 0, 255);
} }
void Voxel::set_geometry_type(GeometryType type) { void VoxelBlockyModel::set_geometry_type(GeometryType type) {
if (type == _geometry_type) { if (type == _geometry_type) {
return; return;
} }
@ -138,28 +138,28 @@ void Voxel::set_geometry_type(GeometryType type) {
#endif #endif
} }
Voxel::GeometryType Voxel::get_geometry_type() const { VoxelBlockyModel::GeometryType VoxelBlockyModel::get_geometry_type() const {
return _geometry_type; return _geometry_type;
} }
void Voxel::set_custom_mesh(Ref<Mesh> mesh) { void VoxelBlockyModel::set_custom_mesh(Ref<Mesh> mesh) {
_custom_mesh = mesh; _custom_mesh = mesh;
} }
void Voxel::set_cube_geometry() {} void VoxelBlockyModel::set_cube_geometry() {}
void Voxel::set_random_tickable(bool rt) { void VoxelBlockyModel::set_random_tickable(bool rt) {
_random_tickable = rt; _random_tickable = rt;
} }
void Voxel::set_cube_uv_side(int side, Vector2 tile_pos) { void VoxelBlockyModel::set_cube_uv_side(int side, Vector2 tile_pos) {
_cube_tiles[side] = tile_pos; _cube_tiles[side] = tile_pos;
} }
Ref<Resource> Voxel::duplicate(bool p_subresources) const { Ref<Resource> VoxelBlockyModel::duplicate(bool p_subresources) const {
Ref<Voxel> d_ref; Ref<VoxelBlockyModel> d_ref;
d_ref.instantiate(); d_ref.instantiate();
Voxel &d = **d_ref; VoxelBlockyModel &d = **d_ref;
d._id = -1; d._id = -1;
@ -183,11 +183,12 @@ Ref<Resource> Voxel::duplicate(bool p_subresources) const {
return d_ref; return d_ref;
} }
void Voxel::set_collision_mask(uint32_t mask) { void VoxelBlockyModel::set_collision_mask(uint32_t mask) {
_collision_mask = mask; _collision_mask = mask;
} }
static void bake_cube_geometry(Voxel &config, Voxel::BakedData &baked_data, int p_atlas_size, bool bake_tangents) { static void bake_cube_geometry(
VoxelBlockyModel &config, VoxelBlockyModel::BakedData &baked_data, int p_atlas_size, bool bake_tangents) {
const float sy = 1.0; const float sy = 1.0;
for (unsigned int side = 0; side < Cube::SIDE_COUNT; ++side) { for (unsigned int side = 0; side < Cube::SIDE_COUNT; ++side) {
@ -244,7 +245,7 @@ static void bake_cube_geometry(Voxel &config, Voxel::BakedData &baked_data, int
baked_data.empty = false; baked_data.empty = false;
} }
static void bake_mesh_geometry(Voxel &config, Voxel::BakedData &baked_data, bool bake_tangents) { static void bake_mesh_geometry(VoxelBlockyModel &config, VoxelBlockyModel::BakedData &baked_data, bool bake_tangents) {
Ref<Mesh> mesh = config.get_custom_mesh(); Ref<Mesh> mesh = config.get_custom_mesh();
if (mesh.is_null()) { if (mesh.is_null()) {
@ -328,7 +329,7 @@ static void bake_mesh_geometry(Voxel &config, Voxel::BakedData &baked_data, bool
HashMap<int, int> added_regular_indices; HashMap<int, int> added_regular_indices;
FixedArray<Vector3, 3> tri_positions; FixedArray<Vector3, 3> tri_positions;
Voxel::BakedData::Model &model = baked_data.model; VoxelBlockyModel::BakedData::Model &model = baked_data.model;
for (int i = 0; i < indices.size(); i += 3) { for (int i = 0; i < indices.size(); i += 3) {
Cube::SideAxis side; Cube::SideAxis side;
@ -442,7 +443,7 @@ static void bake_mesh_geometry(Voxel &config, Voxel::BakedData &baked_data, bool
} }
} }
void Voxel::bake(BakedData &baked_data, int p_atlas_size, bool bake_tangents) { void VoxelBlockyModel::bake(BakedData &baked_data, int p_atlas_size, bool bake_tangents) {
baked_data.clear(); baked_data.clear();
// baked_data.contributes_to_ao is set by the side culling phase // baked_data.contributes_to_ao is set by the side culling phase
@ -471,7 +472,7 @@ void Voxel::bake(BakedData &baked_data, int p_atlas_size, bool bake_tangents) {
_empty = baked_data.empty; _empty = baked_data.empty;
} }
Array Voxel::_b_get_collision_aabbs() const { Array VoxelBlockyModel::_b_get_collision_aabbs() const {
Array array; Array array;
array.resize(_collision_aabbs.size()); array.resize(_collision_aabbs.size());
for (size_t i = 0; i < _collision_aabbs.size(); ++i) { for (size_t i = 0; i < _collision_aabbs.size(); ++i) {
@ -480,7 +481,7 @@ Array Voxel::_b_get_collision_aabbs() const {
return array; return array;
} }
void Voxel::_b_set_collision_aabbs(Array array) { void VoxelBlockyModel::_b_set_collision_aabbs(Array array) {
for (int i = 0; i < array.size(); ++i) { for (int i = 0; i < array.size(); ++i) {
const Variant v = array[i]; const Variant v = array[i];
ERR_FAIL_COND(v.get_type() != Variant::AABB); ERR_FAIL_COND(v.get_type() != Variant::AABB);
@ -492,41 +493,42 @@ void Voxel::_b_set_collision_aabbs(Array array) {
} }
} }
void Voxel::_bind_methods() { void VoxelBlockyModel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_voxel_name", "name"), &Voxel::set_voxel_name); ClassDB::bind_method(D_METHOD("set_voxel_name", "name"), &VoxelBlockyModel::set_voxel_name);
ClassDB::bind_method(D_METHOD("get_voxel_name"), &Voxel::get_voxel_name); ClassDB::bind_method(D_METHOD("get_voxel_name"), &VoxelBlockyModel::get_voxel_name);
ClassDB::bind_method(D_METHOD("set_id", "id"), &Voxel::set_id); ClassDB::bind_method(D_METHOD("set_id", "id"), &VoxelBlockyModel::set_id);
ClassDB::bind_method(D_METHOD("get_id"), &Voxel::get_id); ClassDB::bind_method(D_METHOD("get_id"), &VoxelBlockyModel::get_id);
ClassDB::bind_method(D_METHOD("set_color", "color"), &Voxel::set_color); ClassDB::bind_method(D_METHOD("set_color", "color"), &VoxelBlockyModel::set_color);
ClassDB::bind_method(D_METHOD("get_color"), &Voxel::get_color); ClassDB::bind_method(D_METHOD("get_color"), &VoxelBlockyModel::get_color);
ClassDB::bind_method(D_METHOD("set_transparent", "transparent"), &Voxel::set_transparent); ClassDB::bind_method(D_METHOD("set_transparent", "transparent"), &VoxelBlockyModel::set_transparent);
ClassDB::bind_method(D_METHOD("is_transparent"), &Voxel::is_transparent); ClassDB::bind_method(D_METHOD("is_transparent"), &VoxelBlockyModel::is_transparent);
ClassDB::bind_method(D_METHOD("set_transparency_index", "transparency_index"), &Voxel::set_transparency_index); ClassDB::bind_method(
ClassDB::bind_method(D_METHOD("get_transparency_index"), &Voxel::get_transparency_index); D_METHOD("set_transparency_index", "transparency_index"), &VoxelBlockyModel::set_transparency_index);
ClassDB::bind_method(D_METHOD("get_transparency_index"), &VoxelBlockyModel::get_transparency_index);
ClassDB::bind_method(D_METHOD("set_random_tickable", "rt"), &Voxel::set_random_tickable); ClassDB::bind_method(D_METHOD("set_random_tickable", "rt"), &VoxelBlockyModel::set_random_tickable);
ClassDB::bind_method(D_METHOD("is_random_tickable"), &Voxel::is_random_tickable); ClassDB::bind_method(D_METHOD("is_random_tickable"), &VoxelBlockyModel::is_random_tickable);
ClassDB::bind_method(D_METHOD("set_material_id", "id"), &Voxel::set_material_id); ClassDB::bind_method(D_METHOD("set_material_id", "id"), &VoxelBlockyModel::set_material_id);
ClassDB::bind_method(D_METHOD("get_material_id"), &Voxel::get_material_id); ClassDB::bind_method(D_METHOD("get_material_id"), &VoxelBlockyModel::get_material_id);
ClassDB::bind_method(D_METHOD("set_geometry_type", "type"), &Voxel::set_geometry_type); ClassDB::bind_method(D_METHOD("set_geometry_type", "type"), &VoxelBlockyModel::set_geometry_type);
ClassDB::bind_method(D_METHOD("get_geometry_type"), &Voxel::get_geometry_type); ClassDB::bind_method(D_METHOD("get_geometry_type"), &VoxelBlockyModel::get_geometry_type);
ClassDB::bind_method(D_METHOD("set_custom_mesh", "type"), &Voxel::set_custom_mesh); ClassDB::bind_method(D_METHOD("set_custom_mesh", "type"), &VoxelBlockyModel::set_custom_mesh);
ClassDB::bind_method(D_METHOD("get_custom_mesh"), &Voxel::get_custom_mesh); ClassDB::bind_method(D_METHOD("get_custom_mesh"), &VoxelBlockyModel::get_custom_mesh);
ClassDB::bind_method(D_METHOD("set_collision_aabbs", "aabbs"), &Voxel::_b_set_collision_aabbs); ClassDB::bind_method(D_METHOD("set_collision_aabbs", "aabbs"), &VoxelBlockyModel::_b_set_collision_aabbs);
ClassDB::bind_method(D_METHOD("get_collision_aabbs"), &Voxel::_b_get_collision_aabbs); ClassDB::bind_method(D_METHOD("get_collision_aabbs"), &VoxelBlockyModel::_b_get_collision_aabbs);
ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &Voxel::set_collision_mask); ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &VoxelBlockyModel::set_collision_mask);
ClassDB::bind_method(D_METHOD("get_collision_mask"), &Voxel::get_collision_mask); ClassDB::bind_method(D_METHOD("get_collision_mask"), &VoxelBlockyModel::get_collision_mask);
ClassDB::bind_method(D_METHOD("is_empty"), &Voxel::is_empty); ClassDB::bind_method(D_METHOD("is_empty"), &VoxelBlockyModel::is_empty);
// TODO Update to StringName in Godot 4 // TODO Update to StringName in Godot 4
ADD_PROPERTY(PropertyInfo(Variant::STRING, "voxel_name"), "set_voxel_name", "get_voxel_name"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "voxel_name"), "set_voxel_name", "get_voxel_name");

View File

@ -9,14 +9,13 @@
namespace zylann::voxel { namespace zylann::voxel {
class VoxelLibrary; class VoxelBlockyLibrary;
// TODO Rename VoxelBlockyLibraryItem?
// Definition of one type of voxel for use with `VoxelMesherBlocky`. // Definition of one type of voxel for use with `VoxelMesherBlocky`.
// A voxel can be a simple coloured cube, or a more complex model. // A voxel can be a simple coloured cube, or a more complex model.
// Important: it is recommended that you create voxels from a library rather than using new(). // Important: it is recommended that you create voxels from a library rather than using new().
class Voxel : public Resource { class VoxelBlockyModel : public Resource {
GDCLASS(Voxel, Resource) GDCLASS(VoxelBlockyModel, Resource)
public: public:
// Convention to mean "nothing". // Convention to mean "nothing".
@ -72,7 +71,7 @@ public:
} }
}; };
Voxel(); VoxelBlockyModel();
enum Side { enum Side {
SIDE_NEGATIVE_X = Cube::SIDE_NEGATIVE_X, SIDE_NEGATIVE_X = Cube::SIDE_NEGATIVE_X,
@ -204,7 +203,7 @@ private:
} // namespace zylann::voxel } // namespace zylann::voxel
VARIANT_ENUM_CAST(zylann::voxel::Voxel::GeometryType) VARIANT_ENUM_CAST(zylann::voxel::VoxelBlockyModel::GeometryType)
VARIANT_ENUM_CAST(zylann::voxel::Voxel::Side) VARIANT_ENUM_CAST(zylann::voxel::VoxelBlockyModel::Side)
#endif // VOXEL_TYPE_H #endif // VOXEL_TYPE_H

View File

@ -18,10 +18,10 @@ const int g_opposite_side[6] = {
Cube::SIDE_NEGATIVE_Z // Cube::SIDE_NEGATIVE_Z //
}; };
inline bool is_face_visible( inline bool is_face_visible(const VoxelBlockyLibrary::BakedData &lib, const VoxelBlockyModel::BakedData &vt,
const VoxelLibrary::BakedData &lib, const Voxel::BakedData &vt, uint32_t other_voxel_id, int side) { uint32_t other_voxel_id, int side) {
if (other_voxel_id < lib.models.size()) { if (other_voxel_id < lib.models.size()) {
const Voxel::BakedData &other_vt = lib.models[other_voxel_id]; const VoxelBlockyModel::BakedData &other_vt = lib.models[other_voxel_id];
if (other_vt.empty || (other_vt.transparency_index > vt.transparency_index)) { if (other_vt.empty || (other_vt.transparency_index > vt.transparency_index)) {
return true; return true;
} else { } else {
@ -34,9 +34,9 @@ inline bool is_face_visible(
return true; return true;
} }
inline bool contributes_to_ao(const VoxelLibrary::BakedData &lib, uint32_t voxel_id) { inline bool contributes_to_ao(const VoxelBlockyLibrary::BakedData &lib, uint32_t voxel_id) {
if (voxel_id < lib.models.size()) { if (voxel_id < lib.models.size()) {
const Voxel::BakedData &t = lib.models[voxel_id]; const VoxelBlockyModel::BakedData &t = lib.models[voxel_id];
return t.contributes_to_ao; return t.contributes_to_ao;
} }
return true; return true;
@ -47,7 +47,7 @@ inline bool contributes_to_ao(const VoxelLibrary::BakedData &lib, uint32_t voxel
template <typename Type_T> template <typename Type_T>
void generate_blocky_mesh( void generate_blocky_mesh(
FixedArray<VoxelMesherBlocky::Arrays, VoxelMesherBlocky::MAX_MATERIALS> &out_arrays_per_material, FixedArray<VoxelMesherBlocky::Arrays, VoxelMesherBlocky::MAX_MATERIALS> &out_arrays_per_material,
const Span<Type_T> type_buffer, const Vector3i block_size, const VoxelLibrary::BakedData &library, const Span<Type_T> type_buffer, const Vector3i block_size, const VoxelBlockyLibrary::BakedData &library,
bool bake_occlusion, float baked_occlusion_darkness) { bool bake_occlusion, float baked_occlusion_darkness) {
ERR_FAIL_COND(block_size.x < static_cast<int>(2 * VoxelMesherBlocky::PADDING) || ERR_FAIL_COND(block_size.x < static_cast<int>(2 * VoxelMesherBlocky::PADDING) ||
block_size.y < static_cast<int>(2 * VoxelMesherBlocky::PADDING) || block_size.y < static_cast<int>(2 * VoxelMesherBlocky::PADDING) ||
@ -131,7 +131,7 @@ void generate_blocky_mesh(
const int voxel_id = type_buffer[voxel_index]; const int voxel_id = type_buffer[voxel_index];
if (voxel_id != 0 && library.has_model(voxel_id)) { if (voxel_id != 0 && library.has_model(voxel_id)) {
const Voxel::BakedData &voxel = library.models[voxel_id]; const VoxelBlockyModel::BakedData &voxel = library.models[voxel_id];
VoxelMesherBlocky::Arrays &arrays = out_arrays_per_material[voxel.material_id]; VoxelMesherBlocky::Arrays &arrays = out_arrays_per_material[voxel.material_id];
int &index_offset = index_offsets[voxel.material_id]; int &index_offset = index_offsets[voxel.material_id];
@ -340,12 +340,12 @@ VoxelMesherBlocky::VoxelMesherBlocky() {
VoxelMesherBlocky::~VoxelMesherBlocky() {} VoxelMesherBlocky::~VoxelMesherBlocky() {}
void VoxelMesherBlocky::set_library(Ref<VoxelLibrary> library) { void VoxelMesherBlocky::set_library(Ref<VoxelBlockyLibrary> library) {
RWLockWrite wlock(_parameters_lock); RWLockWrite wlock(_parameters_lock);
_parameters.library = library; _parameters.library = library;
} }
Ref<VoxelLibrary> VoxelMesherBlocky::get_library() const { Ref<VoxelBlockyLibrary> VoxelMesherBlocky::get_library() const {
RWLockRead rlock(_parameters_lock); RWLockRead rlock(_parameters_lock);
return _parameters.library; return _parameters.library;
} }
@ -451,7 +451,7 @@ void VoxelMesherBlocky::build(VoxelMesher::Output &output, const VoxelMesher::In
{ {
// We can only access baked data. Only this data is made for multithreaded access. // We can only access baked data. Only this data is made for multithreaded access.
RWLockRead lock(params.library->get_baked_data_rw_lock()); RWLockRead lock(params.library->get_baked_data_rw_lock());
const VoxelLibrary::BakedData &library_baked_data = params.library->get_baked_data(); const VoxelBlockyLibrary::BakedData &library_baked_data = params.library->get_baked_data();
switch (channel_depth) { switch (channel_depth) {
case VoxelBufferInternal::DEPTH_8_BIT: case VoxelBufferInternal::DEPTH_8_BIT:

View File

@ -2,16 +2,14 @@
#define VOXEL_MESHER_BLOCKY_H #define VOXEL_MESHER_BLOCKY_H
#include "../voxel_mesher.h" #include "../voxel_mesher.h"
#include "voxel_library.h" #include "voxel_blocky_library.h"
#include <core/object/ref_counted.h> #include <core/object/ref_counted.h>
#include <scene/resources/mesh.h> #include <scene/resources/mesh.h>
#include <vector> #include <vector>
namespace zylann::voxel { namespace zylann::voxel {
// TODO Rename VoxelMesherModelBatch // Interprets voxel values as indexes to models in a VoxelBlockyLibrary, and batches them together.
// Interprets voxel values as indexes to models in a VoxelLibrary, and batches them together.
// Overlapping faces are removed from the final mesh. // Overlapping faces are removed from the final mesh.
class VoxelMesherBlocky : public VoxelMesher { class VoxelMesherBlocky : public VoxelMesher {
GDCLASS(VoxelMesherBlocky, VoxelMesher) GDCLASS(VoxelMesherBlocky, VoxelMesher)
@ -23,8 +21,8 @@ public:
VoxelMesherBlocky(); VoxelMesherBlocky();
~VoxelMesherBlocky(); ~VoxelMesherBlocky();
void set_library(Ref<VoxelLibrary> library); void set_library(Ref<VoxelBlockyLibrary> library);
Ref<VoxelLibrary> get_library() const; Ref<VoxelBlockyLibrary> get_library() const;
void set_occlusion_darkness(float darkness); void set_occlusion_darkness(float darkness);
float get_occlusion_darkness() const; float get_occlusion_darkness() const;
@ -68,7 +66,7 @@ private:
struct Parameters { struct Parameters {
float baked_occlusion_darkness = 0.8; float baked_occlusion_darkness = 0.8;
bool bake_occlusion = true; bool bake_occlusion = true;
Ref<VoxelLibrary> library; Ref<VoxelBlockyLibrary> library;
}; };
struct Cache { struct Cache {

View File

@ -13,7 +13,7 @@
#include "generators/simple/voxel_generator_noise_2d.h" #include "generators/simple/voxel_generator_noise_2d.h"
#include "generators/simple/voxel_generator_waves.h" #include "generators/simple/voxel_generator_waves.h"
#include "generators/voxel_generator_script.h" #include "generators/voxel_generator_script.h"
#include "meshers/blocky/voxel_library.h" #include "meshers/blocky/voxel_blocky_library.h"
#include "meshers/blocky/voxel_mesher_blocky.h" #include "meshers/blocky/voxel_mesher_blocky.h"
#include "meshers/cubes/voxel_mesher_cubes.h" #include "meshers/cubes/voxel_mesher_cubes.h"
#include "meshers/dmc/voxel_mesher_dmc.h" #include "meshers/dmc/voxel_mesher_dmc.h"
@ -78,8 +78,8 @@ void register_voxel_types() {
ClassDB::register_class<gd::VoxelServer>(); ClassDB::register_class<gd::VoxelServer>();
// Misc // Misc
ClassDB::register_class<Voxel>(); ClassDB::register_class<VoxelBlockyModel>();
ClassDB::register_class<VoxelLibrary>(); ClassDB::register_class<VoxelBlockyLibrary>();
ClassDB::register_class<VoxelColorPalette>(); ClassDB::register_class<VoxelColorPalette>();
ClassDB::register_class<VoxelInstanceLibrary>(); ClassDB::register_class<VoxelInstanceLibrary>();
ClassDB::register_class<VoxelInstanceLibraryItemBase>(); ClassDB::register_class<VoxelInstanceLibraryItemBase>();
@ -170,6 +170,10 @@ void register_voxel_types() {
#ifdef VOXEL_RUN_TESTS #ifdef VOXEL_RUN_TESTS
zylann::voxel::tests::run_voxel_tests(); zylann::voxel::tests::run_voxel_tests();
#endif #endif
// Compatibility with older version
ClassDB::add_compatibility_class("VoxelLibrary", "VoxelBlockyLibrary");
ClassDB::add_compatibility_class("Voxel", "VoxelBlockyModel");
} }
void unregister_voxel_types() { void unregister_voxel_types() {

View File

@ -156,9 +156,9 @@ Vector3 VoxelBoxMover::get_motion(Vector3 p_pos, Vector3 p_motion, AABB p_aabb,
Ref<VoxelMesherCubes> mesher_cubes; Ref<VoxelMesherCubes> mesher_cubes;
if (try_get_as(p_terrain->get_mesher(), mesher_blocky)) { if (try_get_as(p_terrain->get_mesher(), mesher_blocky)) {
Ref<VoxelLibrary> library_ref = mesher_blocky->get_library(); Ref<VoxelBlockyLibrary> library_ref = mesher_blocky->get_library();
ERR_FAIL_COND_V_MSG(library_ref.is_null(), Vector3(), "VoxelMesherBlocky has no library assigned"); ERR_FAIL_COND_V_MSG(library_ref.is_null(), Vector3(), "VoxelMesherBlocky has no library assigned");
VoxelLibrary &library = **library_ref; VoxelBlockyLibrary &library = **library_ref;
const int channel = VoxelBuffer::CHANNEL_TYPE; const int channel = VoxelBuffer::CHANNEL_TYPE;
for (i.z = min_z; i.z < max_z; ++i.z) { for (i.z = min_z; i.z < max_z; ++i.z) {
@ -167,7 +167,7 @@ Vector3 VoxelBoxMover::get_motion(Vector3 p_pos, Vector3 p_motion, AABB p_aabb,
const int type_id = voxels.get_voxel(i, channel); const int type_id = voxels.get_voxel(i, channel);
if (library.has_voxel(type_id)) { if (library.has_voxel(type_id)) {
const Voxel &voxel_type = library.get_voxel_const(type_id); const VoxelBlockyModel &voxel_type = library.get_voxel_const(type_id);
if ((voxel_type.get_collision_mask() & _collision_mask) == 0) { if ((voxel_type.get_collision_mask() & _collision_mask) == 0) {
continue; continue;

View File

@ -754,7 +754,7 @@ void VoxelLodTerrain::set_view_distance(int p_distance_in_voxels) {
void VoxelLodTerrain::start_updater() { void VoxelLodTerrain::start_updater() {
Ref<VoxelMesherBlocky> blocky_mesher = _mesher; Ref<VoxelMesherBlocky> blocky_mesher = _mesher;
if (blocky_mesher.is_valid()) { if (blocky_mesher.is_valid()) {
Ref<VoxelLibrary> library = blocky_mesher->get_library(); Ref<VoxelBlockyLibrary> library = blocky_mesher->get_library();
if (library.is_valid()) { if (library.is_valid()) {
// TODO Any way to execute this function just after the TRES resource loader has finished to load? // TODO Any way to execute this function just after the TRES resource loader has finished to load?
// VoxelLibrary should be baked ahead of time, like MeshLibrary // VoxelLibrary should be baked ahead of time, like MeshLibrary

View File

@ -287,12 +287,12 @@ void VoxelTerrain::set_mesher(Ref<VoxelMesher> mesher) {
update_configuration_warnings(); update_configuration_warnings();
} }
Ref<VoxelLibrary> VoxelTerrain::get_voxel_library() const { Ref<VoxelBlockyLibrary> VoxelTerrain::get_voxel_library() const {
Ref<VoxelMesherBlocky> blocky_mesher = _mesher; Ref<VoxelMesherBlocky> blocky_mesher = _mesher;
if (blocky_mesher.is_valid()) { if (blocky_mesher.is_valid()) {
return blocky_mesher->get_library(); return blocky_mesher->get_library();
} }
return Ref<VoxelLibrary>(); return Ref<VoxelBlockyLibrary>();
} }
void VoxelTerrain::set_generate_collisions(bool enabled) { void VoxelTerrain::set_generate_collisions(bool enabled) {
@ -592,10 +592,10 @@ Dictionary VoxelTerrain::_b_get_statistics() const {
void VoxelTerrain::start_updater() { void VoxelTerrain::start_updater() {
Ref<VoxelMesherBlocky> blocky_mesher = _mesher; Ref<VoxelMesherBlocky> blocky_mesher = _mesher;
if (blocky_mesher.is_valid()) { if (blocky_mesher.is_valid()) {
Ref<VoxelLibrary> library = blocky_mesher->get_library(); Ref<VoxelBlockyLibrary> library = blocky_mesher->get_library();
if (library.is_valid()) { if (library.is_valid()) {
// TODO Any way to execute this function just after the TRES resource loader has finished to load? // TODO Any way to execute this function just after the TRES resource loader has finished to load?
// VoxelLibrary should be baked ahead of time, like MeshLibrary // VoxelBlockyLibrary should be baked ahead of time, like MeshLibrary
library->bake(); library->bake();
} }
} }

View File

@ -90,7 +90,7 @@ public:
void remesh_all_blocks() override; void remesh_all_blocks() override;
// For convenience, this is actually stored in a particular type of mesher // For convenience, this is actually stored in a particular type of mesher
Ref<VoxelLibrary> get_voxel_library() const; Ref<VoxelBlockyLibrary> get_voxel_library() const;
struct Stats { struct Stats {
int updated_blocks = 0; int updated_blocks = 0;

View File

@ -2,7 +2,7 @@
#include "../edition/voxel_tool_terrain.h" #include "../edition/voxel_tool_terrain.h"
#include "../generators/graph/range_utility.h" #include "../generators/graph/range_utility.h"
#include "../generators/graph/voxel_generator_graph.h" #include "../generators/graph/voxel_generator_graph.h"
#include "../meshers/blocky/voxel_library.h" #include "../meshers/blocky/voxel_blocky_library.h"
#include "../storage/voxel_data_map.h" #include "../storage/voxel_data_map.h"
#include "../streams/region/region_file.h" #include "../streams/region/region_file.h"
#include "../streams/voxel_block_serializer.h" #include "../streams/voxel_block_serializer.h"
@ -1133,13 +1133,13 @@ void test_run_blocky_random_tick() {
const Box3i voxel_box(Vector3i(-24, -23, -22), Vector3i(64, 40, 40)); const Box3i voxel_box(Vector3i(-24, -23, -22), Vector3i(64, 40, 40));
// Create library with tickable voxels // Create library with tickable voxels
Ref<VoxelLibrary> library; Ref<VoxelBlockyLibrary> library;
library.instantiate(); library.instantiate();
library->set_voxel_count(3); library->set_voxel_count(3);
library->create_voxel(0, "air"); library->create_voxel(0, "air");
library->create_voxel(1, "non_tickable"); library->create_voxel(1, "non_tickable");
const int TICKABLE_ID = 2; const int TICKABLE_ID = 2;
Ref<Voxel> tickable_voxel = library->create_voxel(TICKABLE_ID, "tickable"); Ref<VoxelBlockyModel> tickable_voxel = library->create_voxel(TICKABLE_ID, "tickable");
tickable_voxel->set_random_tickable(true); tickable_voxel->set_random_tickable(true);
// Create test map // Create test map