Renamed Voxel => VoxelBlockyModel, VoxelLibrary => VoxelBlockyLibrary

master
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.
- `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)
- `Voxel` was renamed `VoxelBlockyModel`
- `VoxelLibrary` was renamed `VoxelBlockyLibrary`
- Known issues
- 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 {
const VoxelDataMap &map;
const VoxelLibrary &library;
const VoxelBlockyLibrary &library;
const uint32_t collision_mask;
bool operator()(const Vector3i pos) const {
@ -55,7 +55,7 @@ Ref<VoxelRaycastResult> VoxelToolTerrain::raycast(
return false;
}
const Voxel &voxel = library.get_voxel_const(v);
const VoxelBlockyModel &voxel = library.get_voxel_const(v);
if (voxel.is_empty()) {
return false;
}
@ -92,7 +92,7 @@ Ref<VoxelRaycastResult> VoxelToolTerrain::raycast(
const float max_distance = p_max_distance / to_world_scale;
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()) {
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));
}
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)) {
ERR_FAIL_COND(batch_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) {
const uint64_t v = voxels.get_voxel(0, 0, 0, channel);
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()) {
// Skip whole block
continue;
@ -305,7 +305,7 @@ void VoxelToolTerrain::run_blocky_random_tick_static(VoxelDataMap &map, Box3i vo
const Pick pick = picks[i];
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()) {
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 };
const VoxelLibrary &lib = **_terrain->get_voxel_library();
const VoxelBlockyLibrary &lib = **_terrain->get_voxel_library();
VoxelDataMap &map = _terrain->get_storage();
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 {
class VoxelTerrain;
class VoxelLibrary;
class VoxelBlockyLibrary;
class VoxelDataMap;
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)
// 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));
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 <core/math/geometry_2d.h>
@ -8,15 +8,15 @@
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();
}
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);
if (type_count == _voxel_types.size()) {
return;
@ -27,9 +27,9 @@ void VoxelLibrary::set_voxel_count(unsigned int type_count) {
_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) {
const Ref<Voxel> &v = _voxel_types[i];
const Ref<VoxelBlockyModel> &v = _voxel_types[i];
if (v.is_null()) {
continue;
}
@ -40,20 +40,20 @@ int VoxelLibrary::get_voxel_index_from_name(StringName name) const {
return -1;
}
void VoxelLibrary::load_default() {
void VoxelBlockyLibrary::load_default() {
set_voxel_count(2);
Ref<Voxel> air = create_voxel(0, "air");
Ref<VoxelBlockyModel> air = create_voxel(0, "air");
air->set_transparent(true);
Ref<Voxel> solid = create_voxel(1, "solid");
Ref<VoxelBlockyModel> solid = create_voxel(1, "solid");
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
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") {
// int v = p_value;
@ -73,7 +73,7 @@ bool VoxelLibrary::_set(const StringName &p_name, const Variant &p_value) {
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") {
// r_ret = _max_count;
@ -91,33 +91,33 @@ bool VoxelLibrary::_get(const StringName &p_name, Variant &r_ret) const {
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) {
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);
_atlas_size = s;
_needs_baking = true;
}
void VoxelLibrary::set_bake_tangents(bool bt) {
void VoxelBlockyLibrary::set_bake_tangents(bool bt) {
_bake_tangents = bt;
_needs_baking = true;
}
Ref<Voxel> VoxelLibrary::create_voxel(unsigned int id, String name) {
ERR_FAIL_COND_V(id >= _voxel_types.size(), Ref<Voxel>());
Ref<Voxel> voxel(memnew(Voxel));
Ref<VoxelBlockyModel> VoxelBlockyLibrary::create_voxel(unsigned int id, String name) {
ERR_FAIL_COND_V(id >= _voxel_types.size(), Ref<VoxelBlockyModel>());
Ref<VoxelBlockyModel> voxel(memnew(VoxelBlockyModel));
voxel->set_id(id);
voxel->set_voxel_name(name);
_voxel_types[id] = 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);
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);
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());
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()) {
_voxel_types[i]->bake(_baked_data.models[i], _atlas_size, _bake_tangents);
} else {
@ -184,7 +184,7 @@ void VoxelLibrary::bake() {
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.
// 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.
@ -216,7 +216,7 @@ void VoxelLibrary::generate_side_culling_matrix() {
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;
for (uint16_t side = 0; side < Cube::SIDE_COUNT; ++side) {
@ -394,23 +394,34 @@ void VoxelLibrary::generate_side_culling_matrix() {
print_line("");*/
}
void VoxelLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_voxel", "id", "name"), &VoxelLibrary::create_voxel);
ClassDB::bind_method(D_METHOD("get_voxel", "id"), &VoxelLibrary::_b_get_voxel);
Ref<VoxelBlockyModel> VoxelBlockyLibrary::_b_get_voxel(unsigned int id) {
ERR_FAIL_COND_V(id >= _voxel_types.size(), Ref<VoxelBlockyModel>());
return _voxel_types[id];
}
ClassDB::bind_method(D_METHOD("set_atlas_size", "square_size"), &VoxelLibrary::set_atlas_size);
ClassDB::bind_method(D_METHOD("get_atlas_size"), &VoxelLibrary::get_atlas_size);
Ref<VoxelBlockyModel> VoxelBlockyLibrary::_b_get_voxel_by_name(StringName name) {
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);
ClassDB::bind_method(D_METHOD("get_voxel_count"), &VoxelLibrary::get_voxel_count);
void VoxelBlockyLibrary::_bind_methods() {
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_bake_tangents", "bake_tangents"), &VoxelLibrary::set_bake_tangents);
ClassDB::bind_method(D_METHOD("set_atlas_size", "square_size"), &VoxelBlockyLibrary::set_atlas_size);
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("get_voxel_by_name", "name"), &VoxelLibrary::_b_get_voxel_by_name);
ClassDB::bind_method(D_METHOD("set_voxel_count", "count"), &VoxelBlockyLibrary::set_voxel_count);
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, "voxel_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR),
@ -420,15 +431,4 @@ void VoxelLibrary::_bind_methods() {
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

View File

@ -2,7 +2,7 @@
#define VOXEL_LIBRARY_H
#include "../../util/dynamic_bitset.h"
#include "voxel.h"
#include "voxel_blocky_model.h"
#include <core/object/ref_counted.h>
namespace zylann::voxel {
@ -10,8 +10,8 @@ namespace zylann::voxel {
// TODO Rename VoxelBlockyLibrary
// Stores a list of models that can be used with VoxelMesherBlocky
class VoxelLibrary : public Resource {
GDCLASS(VoxelLibrary, Resource)
class VoxelBlockyLibrary : public Resource {
GDCLASS(VoxelBlockyLibrary, Resource)
public:
// Limit based on maximum supported by VoxelMesherBlocky
@ -24,7 +24,7 @@ public:
DynamicBitset side_pattern_culling;
unsigned int side_pattern_count = 0;
// 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 {
return i < models.size();
@ -39,8 +39,8 @@ public:
}
};
VoxelLibrary();
~VoxelLibrary();
VoxelBlockyLibrary();
~VoxelBlockyLibrary();
int get_atlas_size() const {
return _atlas_size;
@ -48,7 +48,7 @@ public:
void set_atlas_size(int s);
// 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;
void set_voxel_count(unsigned int type_count);
@ -71,7 +71,7 @@ public:
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];
}
@ -83,7 +83,7 @@ public:
}
private:
void set_voxel(unsigned int id, Ref<Voxel> voxel);
void set_voxel(unsigned int id, Ref<VoxelBlockyModel> voxel);
void generate_side_culling_matrix();
@ -91,15 +91,15 @@ private:
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
Ref<Voxel> _b_get_voxel(unsigned int id);
Ref<Voxel> _b_get_voxel_by_name(StringName name);
Ref<VoxelBlockyModel> _b_get_voxel(unsigned int id);
Ref<VoxelBlockyModel> _b_get_voxel_by_name(StringName name);
static void _bind_methods();
private:
// 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
std::vector<Ref<Voxel>> _voxel_types;
std::vector<Ref<VoxelBlockyModel>> _voxel_types;
int _atlas_size = 16;
bool _needs_baking = true;
bool _bake_tangents = true;

View File

@ -1,11 +1,11 @@
#include "voxel.h"
#include "voxel_blocky_model.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
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) {}
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
}
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;
// 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;
}
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;
if (name.begins_with("cube_tiles/")) {
@ -62,7 +62,7 @@ bool Voxel::_get(const StringName &p_name, Variant &r_ret) const {
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) {
p_list->push_back(PropertyInfo(Variant::FLOAT, "cube_geometry/padding_y"));
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;
}
void Voxel::set_id(int id) {
ERR_FAIL_COND(id < 0 || (unsigned int)id >= VoxelLibrary::MAX_VOXEL_TYPES);
void VoxelBlockyModel::set_id(int id) {
ERR_FAIL_COND(id < 0 || (unsigned int)id >= VoxelBlockyLibrary::MAX_VOXEL_TYPES);
// Cannot modify ID after creation
ERR_FAIL_COND_MSG(_id != -1, "ID cannot be modified after being added to a library");
_id = id;
}
void Voxel::set_color(Color color) {
void VoxelBlockyModel::set_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);
_material_id = id;
}
void Voxel::set_transparent(bool t) {
void VoxelBlockyModel::set_transparent(bool t) {
if (t) {
if (_transparency_index == 0) {
_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);
}
void Voxel::set_geometry_type(GeometryType type) {
void VoxelBlockyModel::set_geometry_type(GeometryType type) {
if (type == _geometry_type) {
return;
}
@ -138,28 +138,28 @@ void Voxel::set_geometry_type(GeometryType type) {
#endif
}
Voxel::GeometryType Voxel::get_geometry_type() const {
VoxelBlockyModel::GeometryType VoxelBlockyModel::get_geometry_type() const {
return _geometry_type;
}
void Voxel::set_custom_mesh(Ref<Mesh> mesh) {
void VoxelBlockyModel::set_custom_mesh(Ref<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;
}
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;
}
Ref<Resource> Voxel::duplicate(bool p_subresources) const {
Ref<Voxel> d_ref;
Ref<Resource> VoxelBlockyModel::duplicate(bool p_subresources) const {
Ref<VoxelBlockyModel> d_ref;
d_ref.instantiate();
Voxel &d = **d_ref;
VoxelBlockyModel &d = **d_ref;
d._id = -1;
@ -183,11 +183,12 @@ Ref<Resource> Voxel::duplicate(bool p_subresources) const {
return d_ref;
}
void Voxel::set_collision_mask(uint32_t mask) {
void VoxelBlockyModel::set_collision_mask(uint32_t 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;
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;
}
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();
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;
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) {
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.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;
}
Array Voxel::_b_get_collision_aabbs() const {
Array VoxelBlockyModel::_b_get_collision_aabbs() const {
Array array;
array.resize(_collision_aabbs.size());
for (size_t i = 0; i < _collision_aabbs.size(); ++i) {
@ -480,7 +481,7 @@ Array Voxel::_b_get_collision_aabbs() const {
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) {
const Variant v = array[i];
ERR_FAIL_COND(v.get_type() != Variant::AABB);
@ -492,41 +493,42 @@ void Voxel::_b_set_collision_aabbs(Array array) {
}
}
void Voxel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_voxel_name", "name"), &Voxel::set_voxel_name);
ClassDB::bind_method(D_METHOD("get_voxel_name"), &Voxel::get_voxel_name);
void VoxelBlockyModel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_voxel_name", "name"), &VoxelBlockyModel::set_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("get_id"), &Voxel::get_id);
ClassDB::bind_method(D_METHOD("set_id", "id"), &VoxelBlockyModel::set_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("get_color"), &Voxel::get_color);
ClassDB::bind_method(D_METHOD("set_color", "color"), &VoxelBlockyModel::set_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("is_transparent"), &Voxel::is_transparent);
ClassDB::bind_method(D_METHOD("set_transparent", "transparent"), &VoxelBlockyModel::set_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(D_METHOD("get_transparency_index"), &Voxel::get_transparency_index);
ClassDB::bind_method(
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("is_random_tickable"), &Voxel::is_random_tickable);
ClassDB::bind_method(D_METHOD("set_random_tickable", "rt"), &VoxelBlockyModel::set_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("get_material_id"), &Voxel::get_material_id);
ClassDB::bind_method(D_METHOD("set_material_id", "id"), &VoxelBlockyModel::set_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("get_geometry_type"), &Voxel::get_geometry_type);
ClassDB::bind_method(D_METHOD("set_geometry_type", "type"), &VoxelBlockyModel::set_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("get_custom_mesh"), &Voxel::get_custom_mesh);
ClassDB::bind_method(D_METHOD("set_custom_mesh", "type"), &VoxelBlockyModel::set_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("get_collision_aabbs"), &Voxel::_b_get_collision_aabbs);
ClassDB::bind_method(D_METHOD("set_collision_aabbs", "aabbs"), &VoxelBlockyModel::_b_set_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("get_collision_mask"), &Voxel::get_collision_mask);
ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &VoxelBlockyModel::set_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
ADD_PROPERTY(PropertyInfo(Variant::STRING, "voxel_name"), "set_voxel_name", "get_voxel_name");

View File

@ -9,14 +9,13 @@
namespace zylann::voxel {
class VoxelLibrary;
class VoxelBlockyLibrary;
// TODO Rename VoxelBlockyLibraryItem?
// Definition of one type of voxel for use with `VoxelMesherBlocky`.
// 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().
class Voxel : public Resource {
GDCLASS(Voxel, Resource)
class VoxelBlockyModel : public Resource {
GDCLASS(VoxelBlockyModel, Resource)
public:
// Convention to mean "nothing".
@ -72,7 +71,7 @@ public:
}
};
Voxel();
VoxelBlockyModel();
enum Side {
SIDE_NEGATIVE_X = Cube::SIDE_NEGATIVE_X,
@ -204,7 +203,7 @@ private:
} // namespace zylann::voxel
VARIANT_ENUM_CAST(zylann::voxel::Voxel::GeometryType)
VARIANT_ENUM_CAST(zylann::voxel::Voxel::Side)
VARIANT_ENUM_CAST(zylann::voxel::VoxelBlockyModel::GeometryType)
VARIANT_ENUM_CAST(zylann::voxel::VoxelBlockyModel::Side)
#endif // VOXEL_TYPE_H

View File

@ -18,10 +18,10 @@ const int g_opposite_side[6] = {
Cube::SIDE_NEGATIVE_Z //
};
inline bool is_face_visible(
const VoxelLibrary::BakedData &lib, const Voxel::BakedData &vt, uint32_t other_voxel_id, int side) {
inline bool is_face_visible(const VoxelBlockyLibrary::BakedData &lib, const VoxelBlockyModel::BakedData &vt,
uint32_t other_voxel_id, int side) {
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)) {
return true;
} else {
@ -34,9 +34,9 @@ inline bool is_face_visible(
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()) {
const Voxel::BakedData &t = lib.models[voxel_id];
const VoxelBlockyModel::BakedData &t = lib.models[voxel_id];
return t.contributes_to_ao;
}
return true;
@ -47,7 +47,7 @@ inline bool contributes_to_ao(const VoxelLibrary::BakedData &lib, uint32_t voxel
template <typename Type_T>
void generate_blocky_mesh(
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) {
ERR_FAIL_COND(block_size.x < 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];
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];
int &index_offset = index_offsets[voxel.material_id];
@ -340,12 +340,12 @@ VoxelMesherBlocky::VoxelMesherBlocky() {
VoxelMesherBlocky::~VoxelMesherBlocky() {}
void VoxelMesherBlocky::set_library(Ref<VoxelLibrary> library) {
void VoxelMesherBlocky::set_library(Ref<VoxelBlockyLibrary> library) {
RWLockWrite wlock(_parameters_lock);
_parameters.library = library;
}
Ref<VoxelLibrary> VoxelMesherBlocky::get_library() const {
Ref<VoxelBlockyLibrary> VoxelMesherBlocky::get_library() const {
RWLockRead rlock(_parameters_lock);
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.
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) {
case VoxelBufferInternal::DEPTH_8_BIT:

View File

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

View File

@ -13,7 +13,7 @@
#include "generators/simple/voxel_generator_noise_2d.h"
#include "generators/simple/voxel_generator_waves.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/cubes/voxel_mesher_cubes.h"
#include "meshers/dmc/voxel_mesher_dmc.h"
@ -78,8 +78,8 @@ void register_voxel_types() {
ClassDB::register_class<gd::VoxelServer>();
// Misc
ClassDB::register_class<Voxel>();
ClassDB::register_class<VoxelLibrary>();
ClassDB::register_class<VoxelBlockyModel>();
ClassDB::register_class<VoxelBlockyLibrary>();
ClassDB::register_class<VoxelColorPalette>();
ClassDB::register_class<VoxelInstanceLibrary>();
ClassDB::register_class<VoxelInstanceLibraryItemBase>();
@ -170,6 +170,10 @@ void register_voxel_types() {
#ifdef VOXEL_RUN_TESTS
zylann::voxel::tests::run_voxel_tests();
#endif
// Compatibility with older version
ClassDB::add_compatibility_class("VoxelLibrary", "VoxelBlockyLibrary");
ClassDB::add_compatibility_class("Voxel", "VoxelBlockyModel");
}
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;
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");
VoxelLibrary &library = **library_ref;
VoxelBlockyLibrary &library = **library_ref;
const int channel = VoxelBuffer::CHANNEL_TYPE;
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);
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) {
continue;

View File

@ -754,7 +754,7 @@ void VoxelLodTerrain::set_view_distance(int p_distance_in_voxels) {
void VoxelLodTerrain::start_updater() {
Ref<VoxelMesherBlocky> blocky_mesher = _mesher;
if (blocky_mesher.is_valid()) {
Ref<VoxelLibrary> library = blocky_mesher->get_library();
Ref<VoxelBlockyLibrary> library = blocky_mesher->get_library();
if (library.is_valid()) {
// 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

View File

@ -287,12 +287,12 @@ void VoxelTerrain::set_mesher(Ref<VoxelMesher> mesher) {
update_configuration_warnings();
}
Ref<VoxelLibrary> VoxelTerrain::get_voxel_library() const {
Ref<VoxelBlockyLibrary> VoxelTerrain::get_voxel_library() const {
Ref<VoxelMesherBlocky> blocky_mesher = _mesher;
if (blocky_mesher.is_valid()) {
return blocky_mesher->get_library();
}
return Ref<VoxelLibrary>();
return Ref<VoxelBlockyLibrary>();
}
void VoxelTerrain::set_generate_collisions(bool enabled) {
@ -592,10 +592,10 @@ Dictionary VoxelTerrain::_b_get_statistics() const {
void VoxelTerrain::start_updater() {
Ref<VoxelMesherBlocky> blocky_mesher = _mesher;
if (blocky_mesher.is_valid()) {
Ref<VoxelLibrary> library = blocky_mesher->get_library();
Ref<VoxelBlockyLibrary> library = blocky_mesher->get_library();
if (library.is_valid()) {
// 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();
}
}

View File

@ -90,7 +90,7 @@ public:
void remesh_all_blocks() override;
// 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 {
int updated_blocks = 0;

View File

@ -2,7 +2,7 @@
#include "../edition/voxel_tool_terrain.h"
#include "../generators/graph/range_utility.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 "../streams/region/region_file.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));
// Create library with tickable voxels
Ref<VoxelLibrary> library;
Ref<VoxelBlockyLibrary> library;
library.instantiate();
library->set_voxel_count(3);
library->create_voxel(0, "air");
library->create_voxel(1, "non_tickable");
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);
// Create test map