From fd48f195c63fd95441f68a912b7af09be828ec22 Mon Sep 17 00:00:00 2001 From: Relintai Date: Sat, 9 Nov 2019 21:51:40 +0100 Subject: [PATCH] Implemented the Merger Voxel Library. --- library/voxel_surface.cpp | 3 - library/voxel_surface_merger.cpp | 78 ++++++++++---------- library/voxel_surface_merger.h | 15 ++-- library/voxelman_library_merger.cpp | 106 +++++++++++++++++++++++----- library/voxelman_library_merger.h | 23 +++--- library/voxelman_library_simple.cpp | 1 + 6 files changed, 154 insertions(+), 72 deletions(-) diff --git a/library/voxel_surface.cpp b/library/voxel_surface.cpp index ba01a8a..5e30b99 100644 --- a/library/voxel_surface.cpp +++ b/library/voxel_surface.cpp @@ -27,9 +27,6 @@ Ref VoxelSurface::get_library() const { void VoxelSurface::set_library(Ref library) { _library = (*library); - - if (_library != NULL) - refresh_rects(); } Vector2 VoxelSurface::transform_uv(const VoxelSurfaceSides p_side, const Vector2 p_uv) const { diff --git a/library/voxel_surface_merger.cpp b/library/voxel_surface_merger.cpp index 23cc034..2a077a8 100644 --- a/library/voxel_surface_merger.cpp +++ b/library/voxel_surface_merger.cpp @@ -2,26 +2,18 @@ #include "voxelman_library_merger.h" -int VoxelSurfaceMerger::get_atlas_x(const VoxelSurfaceSides side) const { - int indx = (side * 2); - - return _atlas_positions[indx]; +Ref VoxelSurfaceMerger::get_region(const VoxelSurfaceSides side) { + return _regions[side]; } -void VoxelSurfaceMerger::set_atlas_x(const VoxelSurfaceSides side, int value) { - int indx = (side * 2); - - _atlas_positions[indx] = value; +void VoxelSurfaceMerger::set_region(const VoxelSurfaceSides side, Ref texture) { + _regions[side] = texture; } -int VoxelSurfaceMerger::get_atlas_y(const VoxelSurfaceSides side) const { - int indx = (side * 2) + 1; - - return _atlas_positions[indx]; +Ref VoxelSurfaceMerger::get_texture(const VoxelSurfaceSides side) { + return _textures[side]; } -void VoxelSurfaceMerger::set_atlas_y(const VoxelSurfaceSides side, int value) { - int indx = (side * 2) + 1; - - _atlas_positions[indx] = value; +void VoxelSurfaceMerger::set_texture(const VoxelSurfaceSides side, Ref texture) { + _textures[side] = texture; } void VoxelSurfaceMerger::refresh_rects() { @@ -30,24 +22,38 @@ void VoxelSurfaceMerger::refresh_rects() { ERR_FAIL_COND(!ObjectDB::instance_validate(lib)); for (int i = 0; i < VOXEL_SIDES_COUNT; ++i) { - float culomn = 1.0 / static_cast(lib->get_atlas_columns()); - float row = 1.0 / static_cast(lib->get_atlas_rows()); + if (!_regions[i].is_valid()) { + _rects[i] = Rect2(); + continue; + } + + Ref at = _regions[i]; + Ref tex = at->get_atlas(); + + if (!tex.is_valid()) { + _rects[i] = Rect2(); + continue; + } + + Rect2 region = at->get_region(); + float w = tex->get_width(); + float h = tex->get_height(); Rect2 r; - r.position.x = _atlas_positions[i * 2] * culomn; - r.position.y = _atlas_positions[i * 2 + 1] * row; - - r.size.x = culomn; - r.size.y = row; + r.position.x = region.position.x / w; + r.position.y = region.position.y / h; + r.size.x = region.size.x / w; + r.size.y = region.size.y / h; _rects[i] = r; } } VoxelSurfaceMerger::VoxelSurfaceMerger() { - for (int i = 0; i < VOXEL_SIDES_ARRAY_SIZE; ++i) { - _atlas_positions[i] = 0; + for (int i = 0; i < VOXEL_SIDES_COUNT; ++i) { + _regions[i].unref(); + _textures[i].unref(); } } @@ -55,18 +61,16 @@ VoxelSurfaceMerger::~VoxelSurfaceMerger() { } void VoxelSurfaceMerger::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_atlas_x", "side"), &VoxelSurfaceMerger::get_atlas_x); - ClassDB::bind_method(D_METHOD("set_atlas_x", "side", "value"), &VoxelSurfaceMerger::set_atlas_x); - - ClassDB::bind_method(D_METHOD("get_atlas_y", "side"), &VoxelSurfaceMerger::get_atlas_y); - ClassDB::bind_method(D_METHOD("set_atlas_y", "side", "value"), &VoxelSurfaceMerger::set_atlas_y); + ClassDB::bind_method(D_METHOD("get_region", "side"), &VoxelSurfaceMerger::get_region); + ClassDB::bind_method(D_METHOD("set_region", "side", "texture"), &VoxelSurfaceMerger::set_region); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "region_top", PROPERTY_HINT_RESOURCE_TYPE, "AtlasTexture", 0), "set_region", "get_region", VOXEL_SIDE_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "region_bottom", PROPERTY_HINT_RESOURCE_TYPE, "AtlasTexture", 0), "set_region", "get_region", VOXEL_SIDE_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "region_side", PROPERTY_HINT_RESOURCE_TYPE, "AtlasTexture", 0), "set_region", "get_region", VOXEL_SIDE_SIDE); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "top_atlas_x"), "set_atlas_x", "get_atlas_x", VOXEL_SIDE_TOP); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "top_atlas_y"), "set_atlas_y", "get_atlas_y", VOXEL_SIDE_TOP); + ClassDB::bind_method(D_METHOD("get_texture", "side"), &VoxelSurfaceMerger::get_texture); + ClassDB::bind_method(D_METHOD("set_texture", "side", "texture"), &VoxelSurfaceMerger::set_texture); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_top", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", VOXEL_SIDE_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_bottom", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", VOXEL_SIDE_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_side", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", VOXEL_SIDE_SIDE); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "bottom_atlas_x"), "set_atlas_x", "get_atlas_x", VOXEL_SIDE_BOTTOM); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "bottom_atlas_y"), "set_atlas_y", "get_atlas_y", VOXEL_SIDE_BOTTOM); - - ADD_PROPERTYI(PropertyInfo(Variant::INT, "side_atlas_x"), "set_atlas_x", "get_atlas_x", VOXEL_SIDE_SIDE); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "side_atlas_y"), "set_atlas_y", "get_atlas_y", VOXEL_SIDE_SIDE); } diff --git a/library/voxel_surface_merger.h b/library/voxel_surface_merger.h index 9ca2c05..3ff5bb3 100644 --- a/library/voxel_surface_merger.h +++ b/library/voxel_surface_merger.h @@ -3,15 +3,19 @@ #include "voxel_surface.h" +#include "scene/resources/texture.h" + +#include "../../texture_packer/texture_packer.h" + class VoxelSurfaceMerger : public VoxelSurface { GDCLASS(VoxelSurfaceMerger, VoxelSurface) public: - int get_atlas_x(const VoxelSurfaceSides side) const; - void set_atlas_x(const VoxelSurfaceSides side, int value); + Ref get_region(const VoxelSurfaceSides side); + void set_region(const VoxelSurfaceSides side, Ref texture); - int get_atlas_y(const VoxelSurfaceSides side) const; - void set_atlas_y(const VoxelSurfaceSides side, int value); + Ref get_texture(const VoxelSurfaceSides side); + void set_texture(const VoxelSurfaceSides side, Ref texture); void refresh_rects(); @@ -22,7 +26,8 @@ protected: static void _bind_methods(); private: - int _atlas_positions[VOXEL_SIDES_ARRAY_SIZE]; + Ref _regions[VOXEL_SIDES_COUNT]; + Ref _textures[VOXEL_SIDES_COUNT]; }; #endif diff --git a/library/voxelman_library_merger.cpp b/library/voxelman_library_merger.cpp index ab21c7f..d19cb2d 100644 --- a/library/voxelman_library_merger.cpp +++ b/library/voxelman_library_merger.cpp @@ -1,21 +1,38 @@ #include "voxelman_library_merger.h" -int VoxelmanLibraryMerger::get_atlas_columns() const { - return _atlas_columns; +int VoxelmanLibraryMerger::get_texture_flags() const { + return _packer->get_texture_flags(); +} +void VoxelmanLibraryMerger::set_texture_flags(const int flags) { + _packer->set_texture_flags(flags); } -void VoxelmanLibraryMerger::set_atlas_columns(int s) { - ERR_FAIL_COND(s < 0); - _atlas_columns = s; +int VoxelmanLibraryMerger::get_max_atlas_size() const { + return _packer->get_max_atlas_size(); +} +void VoxelmanLibraryMerger::set_max_atlas_size(const int size) { + _packer->set_max_atlas_size(size); } -int VoxelmanLibraryMerger::get_atlas_rows() const { - return _atlas_rows; +bool VoxelmanLibraryMerger::get_keep_original_atlases() const { + return _packer->get_keep_original_atlases(); +} +void VoxelmanLibraryMerger::set_keep_original_atlases(const bool value) { + _packer->set_keep_original_atlases(value); } -void VoxelmanLibraryMerger::set_atlas_rows(int s) { - ERR_FAIL_COND(s < 0); - _atlas_rows = s; +Color VoxelmanLibraryMerger::get_background_color() const { + return _packer->get_background_color(); +} +void VoxelmanLibraryMerger::set_background_color(const Color color) { + _packer->set_background_color(color); +} + +int VoxelmanLibraryMerger::get_margin() const { + return _packer->get_margin(); +} +void VoxelmanLibraryMerger::set_margin(const int margin) { + _packer->set_margin(margin); } Ref VoxelmanLibraryMerger::get_voxel_surface(int index) const { @@ -73,9 +90,44 @@ void VoxelmanLibraryMerger::set_voxel_surfaces(const Vector &surfaces) } void VoxelmanLibraryMerger::refresh_rects() { + bool texture_added = false; for (int i = 0; i < _voxel_surfaces.size(); i++) { Ref surface = Ref(_voxel_surfaces[i]); + if (surface.is_valid()) { + for (int j = 0; j < VoxelSurface::VOXEL_SIDES_COUNT; ++j) { + Ref tex = surface->get_texture(static_cast(j)); + + if (!tex.is_valid()) + continue; + + if (!_packer->contains_texture(tex)) { + texture_added = true; + surface->set_region(static_cast(j), _packer->add_texture(tex)); + } else { + surface->set_region(static_cast(j), _packer->get_texture(tex)); + } + } + } + } + + if (texture_added) { + _packer->merge(); + + ERR_FAIL_COND(_packer->get_texture_count() == 0); + + Ref tex = _packer->get_generated_texture(0); + + Ref mat = get_material(); + + if (mat.is_valid()) { + mat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, tex); + } + } + + for (int i = 0; i < _voxel_surfaces.size(); i++) { + Ref surface = _voxel_surfaces[i]; + if (surface.is_valid()) { surface->refresh_rects(); } @@ -83,8 +135,11 @@ void VoxelmanLibraryMerger::refresh_rects() { } VoxelmanLibraryMerger::VoxelmanLibraryMerger() { - _atlas_rows = 8; - _atlas_columns = 8; + _packer.instance(); + _packer->set_texture_flags(Texture::FLAG_MIPMAPS | Texture::FLAG_FILTER); + _packer->set_max_atlas_size(1024); + _packer->set_keep_original_atlases(false); + _packer->set_margin(0); } VoxelmanLibraryMerger::~VoxelmanLibraryMerger() { @@ -98,17 +153,30 @@ VoxelmanLibraryMerger::~VoxelmanLibraryMerger() { } _voxel_surfaces.clear(); + + _packer.unref(); } - void VoxelmanLibraryMerger::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_atlas_columns"), &VoxelmanLibraryMerger::get_atlas_columns); - ClassDB::bind_method(D_METHOD("set_atlas_columns", "value"), &VoxelmanLibraryMerger::set_atlas_columns); - ADD_PROPERTY(PropertyInfo(Variant::INT, "atlas_columns"), "set_atlas_columns", "get_atlas_columns"); + ClassDB::bind_method(D_METHOD("get_texture_flags"), &VoxelmanLibraryMerger::get_texture_flags); + ClassDB::bind_method(D_METHOD("set_texture_flags", "flags"), &VoxelmanLibraryMerger::set_texture_flags); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter,Anisotropic Linear,Convert to Linear,Mirrored Repeat,Video Surface"), "set_texture_flags", "get_texture_flags"); - ClassDB::bind_method(D_METHOD("get_atlas_rows"), &VoxelmanLibraryMerger::get_atlas_rows); - ClassDB::bind_method(D_METHOD("set_atlas_rows", "value"), &VoxelmanLibraryMerger::set_atlas_rows); - ADD_PROPERTY(PropertyInfo(Variant::INT, "atlas_rows"), "set_atlas_rows", "get_atlas_rows"); + ClassDB::bind_method(D_METHOD("get_max_atlas_size"), &VoxelmanLibraryMerger::get_max_atlas_size); + ClassDB::bind_method(D_METHOD("set_max_atlas_size", "size"), &VoxelmanLibraryMerger::set_max_atlas_size); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_atlas_size"), "set_max_atlas_size", "get_max_atlas_size"); + + ClassDB::bind_method(D_METHOD("get_keep_original_atlases"), &VoxelmanLibraryMerger::get_keep_original_atlases); + ClassDB::bind_method(D_METHOD("set_keep_original_atlases", "value"), &VoxelmanLibraryMerger::set_keep_original_atlases); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_original_atlases"), "set_keep_original_atlases", "get_keep_original_atlases"); + + ClassDB::bind_method(D_METHOD("get_background_color"), &VoxelmanLibraryMerger::get_background_color); + ClassDB::bind_method(D_METHOD("set_background_color", "color"), &VoxelmanLibraryMerger::set_background_color); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_background_color", "get_background_color"); + + ClassDB::bind_method(D_METHOD("get_margin"), &VoxelmanLibraryMerger::get_margin); + ClassDB::bind_method(D_METHOD("set_margin", "size"), &VoxelmanLibraryMerger::set_margin); + ADD_PROPERTY(PropertyInfo(Variant::INT, "margin"), "set_margin", "get_margin"); ClassDB::bind_method(D_METHOD("get_voxel_surfaces"), &VoxelmanLibraryMerger::get_voxel_surfaces); ClassDB::bind_method(D_METHOD("set_voxel_surfaces"), &VoxelmanLibraryMerger::set_voxel_surfaces); diff --git a/library/voxelman_library_merger.h b/library/voxelman_library_merger.h index 4364a5e..4a13bee 100644 --- a/library/voxelman_library_merger.h +++ b/library/voxelman_library_merger.h @@ -16,11 +16,20 @@ class VoxelmanLibraryMerger : public VoxelmanLibrary { GDCLASS(VoxelmanLibraryMerger, VoxelmanLibrary) public: - int get_atlas_columns() const; - void set_atlas_columns(int s); + int get_texture_flags() const; + void set_texture_flags(const int flags); - int get_atlas_rows() const; - void set_atlas_rows(int s); + int get_max_atlas_size() const; + void set_max_atlas_size(const int size); + + bool get_keep_original_atlases() const; + void set_keep_original_atlases(const bool value); + + Color get_background_color() const; + void set_background_color(const Color color); + + int get_margin() const; + void set_margin(const int margin); Ref get_voxel_surface(int index) const; void set_voxel_surface(int index, Ref value); @@ -41,9 +50,7 @@ protected: private: Vector > _voxel_surfaces; - //atlas - int _atlas_columns; - int _atlas_rows; + Ref _packer; }; -#endif // VOXEL_LIBRARY_H +#endif diff --git a/library/voxelman_library_simple.cpp b/library/voxelman_library_simple.cpp index bbebd27..7e4f002 100644 --- a/library/voxelman_library_simple.cpp +++ b/library/voxelman_library_simple.cpp @@ -66,6 +66,7 @@ void VoxelmanLibrarySimple::set_voxel_surfaces(const Vector &surfaces) if (surface.is_valid()) { surface->set_library(this); + surface->refresh_rects(); } _voxel_surfaces.push_back(surface);