diff --git a/SCsub b/SCsub
index 7d56ca6..2bb6c40 100644
--- a/SCsub
+++ b/SCsub
@@ -32,6 +32,7 @@ sources = [
"library/voxel_surface.cpp",
"library/voxel_surface_simple.cpp",
+ "library/voxel_material_cache.cpp",
"data/voxel_light.cpp",
@@ -84,6 +85,8 @@ sources = [
if has_texture_packer:
sources.append("library/voxel_library_merger.cpp")
sources.append("library/voxel_surface_merger.cpp")
+ sources.append("library/voxel_library_merger_pcm.cpp")
+ sources.append("library/voxel_material_cache_pcm.cpp")
if ARGUMENTS.get('custom_modules_shared', 'no') == 'yes':
# Shared lib compilation
diff --git a/config.py b/config.py
index be52a38..5d24018 100644
--- a/config.py
+++ b/config.py
@@ -24,6 +24,10 @@ def get_doc_classes():
"VoxelLibraryMerger",
"VoxelLibrarySimple",
"VoxelLibrary",
+ "VoxelLibraryMergerPCM",
+
+ "VoxelMaterialCache",
+ "VoxelMaterialCachePCM",
"VoxelCubePoints",
"VoxelMesherCubic",
diff --git a/doc_classes/VoxelChunk.xml b/doc_classes/VoxelChunk.xml
index 5d404c6..8982108 100644
--- a/doc_classes/VoxelChunk.xml
+++ b/doc_classes/VoxelChunk.xml
@@ -702,16 +702,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc_classes/VoxelLibraryMergerPCM.xml b/doc_classes/VoxelLibraryMergerPCM.xml
new file mode 100644
index 0000000..33ac332
--- /dev/null
+++ b/doc_classes/VoxelLibraryMergerPCM.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc_classes/VoxelMaterialCache.xml b/doc_classes/VoxelMaterialCache.xml
new file mode 100644
index 0000000..5dd3e9f
--- /dev/null
+++ b/doc_classes/VoxelMaterialCache.xml
@@ -0,0 +1,194 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc_classes/VoxelMaterialCachePCM.xml b/doc_classes/VoxelMaterialCachePCM.xml
new file mode 100644
index 0000000..80caef9
--- /dev/null
+++ b/doc_classes/VoxelMaterialCachePCM.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/voxel_library.h b/library/voxel_library.h
index b2af09d..84dfdcc 100644
--- a/library/voxel_library.h
+++ b/library/voxel_library.h
@@ -135,7 +135,6 @@ public:
protected:
static void _bind_methods();
-private:
bool _initialized;
Vector[ > _materials;
Vector][ > _liquid_materials;
diff --git a/library/voxel_library_merger.h b/library/voxel_library_merger.h
index c668ec6..a75c77b 100644
--- a/library/voxel_library_merger.h
+++ b/library/voxel_library_merger.h
@@ -104,7 +104,6 @@ protected:
static void _bind_methods();
-private:
Vector][ > _voxel_surfaces;
#ifdef PROPS_PRESENT
Vector][ > _props;
diff --git a/library/voxel_library_merger_pcm.cpp b/library/voxel_library_merger_pcm.cpp
new file mode 100644
index 0000000..4b10d88
--- /dev/null
+++ b/library/voxel_library_merger_pcm.cpp
@@ -0,0 +1,813 @@
+/*
+Copyright (c) 2019-2022 Péter Magyar
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include "voxel_library_merger_pcm.h"
+
+#include "../../texture_packer/texture_packer.h"
+#include "scene/resources/packed_scene.h"
+#include "scene/resources/texture.h"
+
+#ifdef PROPS_PRESENT
+#include "../../props/props/prop_data.h"
+
+#include "../../props/props/prop_data_prop.h"
+
+#if MESH_DATA_RESOURCE_PRESENT
+#include "../../mesh_data_resource/props/prop_data_mesh_data.h"
+#endif
+#endif
+
+#include "voxel_material_cache_pcm.h"
+
+#include "../defines.h"
+
+#include "../world/default/voxel_chunk_default.h"
+
+#include "core/hashfuncs.h"
+
+bool VoxelLibraryMergerPCM::_supports_caching() {
+ return true;
+}
+
+void VoxelLibraryMergerPCM::_material_cache_get_key(Ref chunk) {
+ uint8_t *ch = chunk->channel_get(VoxelChunkDefault::DEFAULT_CHANNEL_TYPE);
+
+ if (!ch) {
+ chunk->material_cache_key_set(0);
+ chunk->material_cache_key_has_set(false);
+
+ return;
+ }
+
+ Vector surfaces;
+
+ uint32_t size = chunk->get_data_size();
+
+ for (uint32_t i = 0; i < size; ++i) {
+ uint8_t v = ch[i];
+
+ if (v == 0) {
+ continue;
+ }
+
+ int ssize = surfaces.size();
+ bool found = false;
+ for (uint8_t j = 0; j < ssize; ++j) {
+ if (surfaces[j] == v) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ surfaces.push_back(v);
+ }
+ }
+
+ if (surfaces.size() == 0) {
+ chunk->material_cache_key_set(0);
+ chunk->material_cache_key_has_set(false);
+
+ return;
+ }
+
+ surfaces.sort();
+
+ String hstr;
+
+ for (int i = 0; i < surfaces.size(); ++i) {
+ hstr += String::num(surfaces[i]) + "|";
+ }
+
+ int hash = static_cast(hstr.hash());
+
+ chunk->material_cache_key_set(hash);
+ chunk->material_cache_key_has_set(true);
+
+ _material_cache_mutex.lock();
+
+ if (_material_cache.has(hash)) {
+ Ref cc = _material_cache[hash];
+
+ if (cc.is_valid()) {
+ cc->inc_ref_count();
+ }
+
+ _material_cache_mutex.unlock();
+
+ return;
+ }
+
+ //print_error("New cache: " + hstr);
+
+ Ref cache;
+ cache.instance();
+ cache->inc_ref_count();
+
+ cache->set_texture_flags(get_texture_flags());
+ cache->set_max_atlas_size(get_max_atlas_size());
+ cache->set_keep_original_atlases(get_keep_original_atlases());
+ cache->set_background_color(get_background_color());
+ cache->set_margin(get_margin());
+
+ for (int i = 0; i < surfaces.size(); ++i) {
+ int s = surfaces[i] - 1;
+
+ if (_voxel_surfaces.size() <= s) {
+ continue;
+ }
+
+ Ref ms = _voxel_surfaces[s];
+
+ if (!ms.is_valid()) {
+ continue;
+ }
+
+ Ref nms = ms->duplicate();
+ nms->set_library(Ref(this));
+ nms->set_id(s);
+
+ cache->surface_add(nms);
+ }
+
+ for (int i = 0; i < _materials.size(); ++i) {
+ Ref m = _materials[i];
+
+ if (!m.is_valid()) {
+ continue;
+ }
+
+ Ref nm = m->duplicate();
+
+ cache->material_add(nm);
+ }
+
+ _material_cache[hash] = cache;
+
+ //unlock here, so if a different thread need the cache it will be able to immediately access the materials and surfaces when it gets it.
+ _material_cache_mutex.unlock();
+
+ //this will generate the atlases
+ cache->refresh_rects();
+}
+
+Ref VoxelLibraryMergerPCM::_material_cache_get(const int key) {
+ _material_cache_mutex.lock();
+
+ ERR_FAIL_COND_V(!_material_cache.has(key), Ref());
+
+ Ref c = _material_cache[key];
+
+ _material_cache_mutex.unlock();
+
+ return c;
+}
+
+void VoxelLibraryMergerPCM::_material_cache_unref(const int key) {
+ _material_cache_mutex.lock();
+
+ if (!_material_cache.has(key)) {
+ return;
+ }
+
+ Ref cc = _material_cache[key];
+
+ if (!cc.is_valid()) {
+ return;
+ }
+
+ cc->dec_ref_count();
+
+ if (cc->get_ref_count() <= 0) {
+ _material_cache.erase(key);
+ }
+
+ _material_cache_mutex.unlock();
+}
+
+void VoxelLibraryMergerPCM::_prop_material_cache_get_key(Ref chunk) {
+ Vector props;
+
+/*
+#ifdef PROPS_PRESENT
+ for (int i = 0; i < chunk->prop_get_count(); ++i) {
+ Ref prop = chunk->prop_get(i);
+
+ ERR_CONTINUE(!prop.is_valid());
+
+ //get pointer's value as uint64
+ uint64_t v = make_uint64_t(*prop);
+
+ int psize = props.size();
+ bool found = false;
+ for (int j = 0; j < psize; ++j) {
+ if (props[j] == v) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ props.push_back(v);
+ }
+ }
+#endif
+*/
+
+#if MESH_DATA_RESOURCE_PRESENT
+ for (int i = 0; i < chunk->mesh_data_resource_get_count(); ++i) {
+ Ref tex = chunk->mesh_data_resource_get_texture(i);
+
+ if (!tex.is_valid())
+ continue;
+
+ //get pointer's value as uint64
+ uint64_t v = make_uint64_t(*tex);
+
+ int psize = props.size();
+ bool found = false;
+ for (int j = 0; j < psize; ++j) {
+ if (props[j] == v) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ props.push_back(v);
+ }
+ }
+#endif
+
+ if (props.size() == 0) {
+ chunk->prop_material_cache_key_set(0);
+ chunk->prop_material_cache_key_has_set(false);
+
+ return;
+ }
+
+ props.sort();
+
+ String hstr;
+
+ for (int i = 0; i < props.size(); ++i) {
+ hstr += String::num_uint64(props[i]) + "|";
+ }
+
+ int hash = static_cast(hstr.hash());
+
+ chunk->prop_material_cache_key_set(hash);
+ chunk->prop_material_cache_key_has_set(true);
+
+ _prop_material_cache_mutex.lock();
+
+ if (_prop_material_cache.has(hash)) {
+ Ref cc = _prop_material_cache[hash];
+
+ if (cc.is_valid()) {
+ cc->inc_ref_count();
+ }
+
+ _prop_material_cache_mutex.unlock();
+
+ return;
+ }
+
+ //print_error("New prop cache: " + hstr);
+
+ Ref cache;
+ cache.instance();
+ cache->inc_ref_count();
+
+ cache->set_texture_flags(get_texture_flags());
+ cache->set_max_atlas_size(get_max_atlas_size());
+ cache->set_keep_original_atlases(get_keep_original_atlases());
+ cache->set_background_color(get_background_color());
+ cache->set_margin(get_margin());
+
+ for (int i = 0; i < _prop_materials.size(); ++i) {
+ Ref m = _prop_materials[i];
+
+ if (!m.is_valid()) {
+ continue;
+ }
+
+ Ref nm = m->duplicate();
+
+ cache->material_add(nm);
+ }
+
+/*
+#ifdef PROPS_PRESENT
+ for (int i = 0; i < chunk->prop_get_count(); ++i) {
+ Ref prop = chunk->prop_get(i);
+
+ ERR_CONTINUE(!prop.is_valid());
+
+ cache->prop_add_textures(prop);
+ }
+#endif
+*/
+
+#if MESH_DATA_RESOURCE_PRESENT
+ for (int i = 0; i < chunk->mesh_data_resource_get_count(); ++i) {
+ Ref tex = chunk->mesh_data_resource_get_texture(i);
+
+ if (!tex.is_valid())
+ continue;
+
+ cache->additional_texture_add(tex);
+ }
+#endif
+
+ _prop_material_cache[hash] = cache;
+
+ //unlock here, so if a different thread need the cache it will be able to immediately access the materials and surfaces when it gets it.
+ _prop_material_cache_mutex.unlock();
+
+ //this will generate the atlases
+ cache->refresh_rects();
+}
+Ref VoxelLibraryMergerPCM::_prop_material_cache_get(const int key) {
+ _prop_material_cache_mutex.lock();
+
+ ERR_FAIL_COND_V(!_prop_material_cache.has(key), Ref());
+
+ Ref c = _prop_material_cache[key];
+
+ _prop_material_cache_mutex.unlock();
+
+ return c;
+}
+void VoxelLibraryMergerPCM::_prop_material_cache_unref(const int key) {
+ _prop_material_cache_mutex.lock();
+
+ if (!_prop_material_cache.has(key)) {
+ return;
+ }
+
+ Ref cc = _prop_material_cache[key];
+
+ if (!cc.is_valid()) {
+ return;
+ }
+
+ cc->dec_ref_count();
+
+ if (cc->get_ref_count() <= 0) {
+ _prop_material_cache.erase(key);
+ }
+
+ _prop_material_cache_mutex.unlock();
+}
+
+int VoxelLibraryMergerPCM::get_texture_flags() const {
+ return _packer->get_texture_flags();
+}
+void VoxelLibraryMergerPCM::set_texture_flags(const int flags) {
+ _packer->set_texture_flags(flags);
+ _prop_packer->set_texture_flags(flags);
+}
+
+int VoxelLibraryMergerPCM::get_max_atlas_size() const {
+ return _packer->get_max_atlas_size();
+}
+void VoxelLibraryMergerPCM::set_max_atlas_size(const int size) {
+ _packer->set_max_atlas_size(size);
+ _prop_packer->set_max_atlas_size(size);
+}
+
+bool VoxelLibraryMergerPCM::get_keep_original_atlases() const {
+ return _packer->get_keep_original_atlases();
+}
+void VoxelLibraryMergerPCM::set_keep_original_atlases(const bool value) {
+ _packer->set_keep_original_atlases(value);
+ _prop_packer->set_keep_original_atlases(value);
+}
+
+Color VoxelLibraryMergerPCM::get_background_color() const {
+ return _packer->get_background_color();
+}
+void VoxelLibraryMergerPCM::set_background_color(const Color &color) {
+ _packer->set_background_color(color);
+ _prop_packer->set_background_color(color);
+}
+
+int VoxelLibraryMergerPCM::get_margin() const {
+ return _packer->get_margin();
+}
+void VoxelLibraryMergerPCM::set_margin(const int margin) {
+ _packer->set_margin(margin);
+ _prop_packer->set_margin(margin);
+}
+
+//Surfaces
+Ref VoxelLibraryMergerPCM::voxel_surface_get(const int index) {
+ ERR_FAIL_INDEX_V(index, _voxel_surfaces.size(), Ref(NULL));
+
+ return _voxel_surfaces[index];
+}
+
+void VoxelLibraryMergerPCM::voxel_surface_add(Ref value) {
+ ERR_FAIL_COND(!value.is_valid());
+
+ value->set_library(Ref(this));
+ value->set_id(_voxel_surfaces.size());
+
+ _voxel_surfaces.push_back(value);
+}
+
+void VoxelLibraryMergerPCM::voxel_surface_set(const int index, Ref value) {
+ ERR_FAIL_COND(index < 0);
+
+ if (_voxel_surfaces.size() < index) {
+ _voxel_surfaces.resize(index + 1);
+ }
+
+ if (_voxel_surfaces[index].is_valid()) {
+ _voxel_surfaces.get(index)->set_library(Ref(NULL));
+ }
+
+ if (value.is_valid()) {
+ value->set_library(Ref(this));
+
+ _voxel_surfaces.set(index, value);
+ }
+}
+
+void VoxelLibraryMergerPCM::voxel_surface_remove(const int index) {
+ _voxel_surfaces.remove(index);
+}
+
+int VoxelLibraryMergerPCM::voxel_surface_get_num() const {
+ return _voxel_surfaces.size();
+}
+
+void VoxelLibraryMergerPCM::voxel_surfaces_clear() {
+ _packer->clear();
+
+ for (int i = 0; i < _voxel_surfaces.size(); i++) {
+ Ref surface = _voxel_surfaces[i];
+
+ if (surface.is_valid()) {
+ surface->set_library(NULL);
+ }
+ }
+
+ _voxel_surfaces.clear();
+}
+
+Vector VoxelLibraryMergerPCM::get_voxel_surfaces() {
+ VARIANT_ARRAY_GET(_voxel_surfaces);
+}
+
+void VoxelLibraryMergerPCM::set_voxel_surfaces(const Vector &surfaces) {
+ _voxel_surfaces.clear();
+
+ for (int i = 0; i < surfaces.size(); i++) {
+ Ref surface = Ref(surfaces[i]);
+
+ if (surface.is_valid()) {
+ surface->set_library(Ref(this));
+ }
+
+ _voxel_surfaces.push_back(surface);
+ }
+}
+
+#ifdef PROPS_PRESENT
+Ref VoxelLibraryMergerPCM::get_prop(const int index) {
+ ERR_FAIL_INDEX_V(index, _props.size(), Ref());
+
+ return _props[index];
+}
+void VoxelLibraryMergerPCM::add_prop(Ref value) {
+ _props.push_back(value);
+}
+bool VoxelLibraryMergerPCM::has_prop(const Ref &value) const {
+ return _props.find(value) != -1;
+}
+void VoxelLibraryMergerPCM::set_prop(const int index, const Ref &value) {
+ ERR_FAIL_INDEX(index, _props.size());
+
+ _props.write[index] = value;
+}
+void VoxelLibraryMergerPCM::remove_prop(const int index) {
+ ERR_FAIL_INDEX(index, _props.size());
+
+ _props.remove(index);
+}
+int VoxelLibraryMergerPCM::get_num_props() const {
+ return _props.size();
+}
+void VoxelLibraryMergerPCM::clear_props() {
+ _props.clear();
+}
+
+Vector VoxelLibraryMergerPCM::get_props() {
+ VARIANT_ARRAY_GET(_props);
+}
+
+void VoxelLibraryMergerPCM::set_props(const Vector &props) {
+ VARIANT_ARRAY_SET(props, _props, PropData);
+}
+
+Rect2 VoxelLibraryMergerPCM::get_prop_uv_rect(const Ref &texture) {
+ if (!texture.is_valid()) {
+ return Rect2(0, 0, 1, 1);
+ }
+
+ Ref at = _prop_packer->get_texture(texture);
+
+ if (!at.is_valid()) {
+ return Rect2(0, 0, 1, 1);
+ }
+
+ Rect2 region = at->get_region();
+
+ Ref tex = at->get_atlas();
+
+ if (!tex.is_valid()) {
+ return Rect2(0, 0, 1, 1);
+ }
+
+ Ref image = tex->get_data();
+
+ if (!image.is_valid()) {
+ return Rect2(0, 0, 1, 1);
+ }
+
+ float w = image->get_width();
+ float h = image->get_height();
+
+ region.position = Size2(region.position.x / w, region.position.y / h);
+ region.size = Size2(region.size.x / w, region.size.y / h);
+
+ return region;
+}
+
+Ref VoxelLibraryMergerPCM::get_prop_packer() {
+ return _prop_packer;
+}
+#endif
+
+void VoxelLibraryMergerPCM::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);
+
+ setup_material_albedo(MATERIAL_INDEX_VOXELS, tex);
+ setup_material_albedo(MATERIAL_INDEX_LIQUID, tex);
+ }
+
+#ifdef PROPS_PRESENT
+ //todo add this back
+ //texture_added = false;
+ for (int i = 0; i < _props.size(); i++) {
+ Ref prop = _props.get(i);
+
+ if (prop.is_valid()) {
+ if (process_prop_textures(prop))
+ texture_added = true;
+ }
+ }
+
+ //if (texture_added) {
+ if (_prop_packer->get_texture_count() > 0) {
+ _prop_packer->merge();
+
+ //ERR_FAIL_COND(_prop_packer->get_texture_count() == 0);
+
+ Ref tex = _prop_packer->get_generated_texture(0);
+
+ setup_material_albedo(MATERIAL_INDEX_PROP, tex);
+ }
+#endif
+
+ for (int i = 0; i < _voxel_surfaces.size(); i++) {
+ Ref surface = _voxel_surfaces[i];
+
+ if (surface.is_valid()) {
+ surface->refresh_rects();
+ }
+ }
+
+ set_initialized(true);
+}
+
+void VoxelLibraryMergerPCM::_setup_material_albedo(const int material_index, const Ref &texture) {
+ Ref mat;
+
+ int count = 0;
+
+ switch (material_index) {
+ case MATERIAL_INDEX_VOXELS:
+ count = material_get_num();
+ break;
+ case MATERIAL_INDEX_LIQUID:
+ count = liquid_material_get_num();
+ break;
+ case MATERIAL_INDEX_PROP:
+ count = prop_material_get_num();
+ break;
+ }
+
+ for (int i = 0; i < count; ++i) {
+ switch (material_index) {
+ case MATERIAL_INDEX_VOXELS:
+ mat = material_get(i);
+ break;
+ case MATERIAL_INDEX_LIQUID:
+ mat = liquid_material_get(i);
+ break;
+ case MATERIAL_INDEX_PROP:
+ mat = prop_material_get(i);
+ break;
+ }
+
+ Ref spmat;
+
+ if (spmat.is_valid()) {
+ spmat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture);
+ return;
+ }
+
+ Ref shmat;
+
+ switch (material_index) {
+ case MATERIAL_INDEX_VOXELS:
+ shmat = material_get(i);
+ break;
+ case MATERIAL_INDEX_LIQUID:
+ shmat = liquid_material_get(i);
+ break;
+ case MATERIAL_INDEX_PROP:
+ shmat = prop_material_get(i);
+ break;
+ }
+
+ if (shmat.is_valid()) {
+ shmat->set_shader_param("texture_albedo", texture);
+ }
+ }
+}
+
+VoxelLibraryMergerPCM::VoxelLibraryMergerPCM() {
+ _packer.instance();
+
+#if GODOT4
+#warning implement
+#else
+ _packer->set_texture_flags(Texture::FLAG_MIPMAPS | Texture::FLAG_FILTER);
+#endif
+
+ _packer->set_max_atlas_size(1024);
+ _packer->set_keep_original_atlases(false);
+ _packer->set_margin(0);
+
+ _prop_packer.instance();
+
+#if GODOT4
+#warning implement
+#else
+ _prop_packer->set_texture_flags(Texture::FLAG_MIPMAPS | Texture::FLAG_FILTER);
+#endif
+
+ _prop_packer->set_max_atlas_size(1024);
+ _prop_packer->set_keep_original_atlases(false);
+ _prop_packer->set_margin(0);
+}
+
+VoxelLibraryMergerPCM::~VoxelLibraryMergerPCM() {
+ for (int i = 0; i < _voxel_surfaces.size(); ++i) {
+ Ref surface = _voxel_surfaces[i];
+
+ if (surface.is_valid()) {
+ surface->set_library(Ref());
+ }
+ }
+
+ _voxel_surfaces.clear();
+
+ _packer->clear();
+ _packer.unref();
+
+ _prop_packer->clear();
+ _prop_packer.unref();
+}
+
+#ifdef PROPS_PRESENT
+bool VoxelLibraryMergerPCM::process_prop_textures(Ref prop) {
+ if (!prop.is_valid()) {
+ return false;
+ }
+
+ bool texture_added = false;
+
+ for (int i = 0; i < prop->get_prop_count(); ++i) {
+ Ref pdm = prop->get_prop(i);
+
+ if (pdm.is_valid()) {
+ Ref tex = pdm->get_texture();
+
+ if (!tex.is_valid())
+ continue;
+
+ if (!_prop_packer->contains_texture(tex)) {
+ _prop_packer->add_texture(tex);
+ texture_added = true;
+ }
+ }
+
+ Ref pdp = prop->get_prop(i);
+
+ if (pdp.is_valid()) {
+ if (process_prop_textures(pdp))
+ texture_added = true;
+ }
+ }
+
+ return texture_added;
+}
+#endif
+
+void VoxelLibraryMergerPCM::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_texture_flags"), &VoxelLibraryMergerPCM::get_texture_flags);
+ ClassDB::bind_method(D_METHOD("set_texture_flags", "flags"), &VoxelLibraryMergerPCM::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_max_atlas_size"), &VoxelLibraryMergerPCM::get_max_atlas_size);
+ ClassDB::bind_method(D_METHOD("set_max_atlas_size", "size"), &VoxelLibraryMergerPCM::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"), &VoxelLibraryMergerPCM::get_keep_original_atlases);
+ ClassDB::bind_method(D_METHOD("set_keep_original_atlases", "value"), &VoxelLibraryMergerPCM::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"), &VoxelLibraryMergerPCM::get_background_color);
+ ClassDB::bind_method(D_METHOD("set_background_color", "color"), &VoxelLibraryMergerPCM::set_background_color);
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_background_color", "get_background_color");
+
+ ClassDB::bind_method(D_METHOD("get_margin"), &VoxelLibraryMergerPCM::get_margin);
+ ClassDB::bind_method(D_METHOD("set_margin", "size"), &VoxelLibraryMergerPCM::set_margin);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "margin"), "set_margin", "get_margin");
+
+ ClassDB::bind_method(D_METHOD("get_voxel_surfaces"), &VoxelLibraryMergerPCM::get_voxel_surfaces);
+ ClassDB::bind_method(D_METHOD("set_voxel_surfaces"), &VoxelLibraryMergerPCM::set_voxel_surfaces);
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "voxel_surfaces", PROPERTY_HINT_NONE, "17/17:VoxelSurfaceMerger", PROPERTY_USAGE_DEFAULT, "VoxelSurfaceMerger"), "set_voxel_surfaces", "get_voxel_surfaces");
+
+#ifdef PROPS_PRESENT
+ ClassDB::bind_method(D_METHOD("get_props"), &VoxelLibraryMergerPCM::get_props);
+ ClassDB::bind_method(D_METHOD("set_props"), &VoxelLibraryMergerPCM::set_props);
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "props", PROPERTY_HINT_NONE, "17/17:PropData", PROPERTY_USAGE_DEFAULT, "PropData"), "set_props", "get_props");
+
+ ClassDB::bind_method(D_METHOD("get_prop_uv_rect", "texture"), &VoxelLibraryMergerPCM::get_prop_uv_rect);
+
+ ClassDB::bind_method(D_METHOD("get_prop_packer"), &VoxelLibraryMergerPCM::get_prop_packer);
+#endif
+
+ ClassDB::bind_method(D_METHOD("_setup_material_albedo", "material_index", "texture"), &VoxelLibraryMergerPCM::_setup_material_albedo);
+}
diff --git a/library/voxel_library_merger_pcm.h b/library/voxel_library_merger_pcm.h
new file mode 100644
index 0000000..818c87d
--- /dev/null
+++ b/library/voxel_library_merger_pcm.h
@@ -0,0 +1,140 @@
+/*
+Copyright (c) 2019-2022 Péter Magyar
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef VOXEL_LIBRARY_MERGER_PCM_H
+#define VOXEL_LIBRARY_MERGER_PCM_H
+
+#include "core/version.h"
+
+#if VERSION_MAJOR > 3
+#include "core/io/resource.h"
+#include "core/templates/map.h"
+#else
+#include "core/resource.h"
+#include "core/map.h"
+#endif
+
+#include "voxel_library.h"
+
+#include "scene/resources/material.h"
+
+#include "../data/voxel_light.h"
+#include "voxel_surface_merger.h"
+
+#include "core/os/mutex.h"
+
+class VoxelSurfaceSimple;
+class VoxelMesher;
+class PackedScene;
+class VoxelMaterialCache;
+class VoxelMaterialCachePCM;
+class TexturePacker;
+class VoxelChunk;
+
+//pcm = per chunk material
+class VoxelLibraryMergerPCM : public VoxelLibrary {
+ GDCLASS(VoxelLibraryMergerPCM, VoxelLibrary);
+
+public:
+ bool _supports_caching();
+
+ void _material_cache_get_key(Ref chunk);
+ Ref _material_cache_get(const int key);
+ void _material_cache_unref(const int key);
+
+ void _prop_material_cache_get_key(Ref chunk);
+ Ref _prop_material_cache_get(const int key);
+ void _prop_material_cache_unref(const int key);
+
+ int get_texture_flags() const;
+ void set_texture_flags(const int flags);
+
+ 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 voxel_surface_get(const int index);
+ void voxel_surface_add(Ref value);
+ void voxel_surface_set(const int index, Ref value);
+ void voxel_surface_remove(const int index);
+ int voxel_surface_get_num() const;
+ void voxel_surfaces_clear();
+
+ Vector get_voxel_surfaces();
+ void set_voxel_surfaces(const Vector &surfaces);
+
+#ifdef PROPS_PRESENT
+ Ref get_prop(const int index);
+ void add_prop(Ref value);
+ bool has_prop(const Ref &value) const;
+ void set_prop(const int index, const Ref &value);
+ void remove_prop(const int index);
+ int get_num_props() const;
+ void clear_props();
+
+ Vector get_props();
+ void set_props(const Vector &props);
+
+ Rect2 get_prop_uv_rect(const Ref &texture);
+
+ Ref get_prop_packer();
+#endif
+
+ void refresh_rects();
+
+ void _setup_material_albedo(const int material_index, const Ref &texture);
+
+ VoxelLibraryMergerPCM();
+ ~VoxelLibraryMergerPCM();
+
+protected:
+#ifdef PROPS_PRESENT
+ bool process_prop_textures(Ref prop);
+#endif
+
+ static void _bind_methods();
+
+ Map > _material_cache;
+ Map > _prop_material_cache;
+
+ Vector][ > _voxel_surfaces;
+#ifdef PROPS_PRESENT
+ Vector][ > _props;
+#endif
+
+ //todo remove these
+ Ref _packer;
+ Ref _prop_packer;
+
+ Mutex _material_cache_mutex;
+ Mutex _prop_material_cache_mutex;
+};
+
+#endif
diff --git a/library/voxel_library_simple.h b/library/voxel_library_simple.h
index 164215d..e04d09a 100644
--- a/library/voxel_library_simple.h
+++ b/library/voxel_library_simple.h
@@ -72,7 +72,6 @@ public:
protected:
static void _bind_methods();
-private:
Vector][ > _voxel_surfaces;
//atlas
diff --git a/library/voxel_material_cache.cpp b/library/voxel_material_cache.cpp
new file mode 100644
index 0000000..47b8ed4
--- /dev/null
+++ b/library/voxel_material_cache.cpp
@@ -0,0 +1,334 @@
+/*
+Copyright (c) 2019-2022 Péter Magyar
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include "voxel_material_cache.h"
+
+#include "../defines.h"
+
+#ifdef PROPS_PRESENT
+#include "../../props/props/prop_data.h"
+#include "../../props/props/prop_data_prop.h"
+
+#if MESH_DATA_RESOURCE_PRESENT
+#include "../../mesh_data_resource/props/prop_data_mesh_data.h"
+#endif
+#endif
+
+bool VoxelMaterialCache::get_initialized() {
+ return _initialized;
+}
+void VoxelMaterialCache::set_initialized(const bool value) {
+ _initialized = value;
+}
+
+int VoxelMaterialCache::get_ref_count() {
+ return _ref_count;
+}
+void VoxelMaterialCache::set_ref_count(const int value) {
+ _ref_count = value;
+}
+void VoxelMaterialCache::inc_ref_count() {
+ _ref_count += 1;
+}
+void VoxelMaterialCache::dec_ref_count() {
+ _ref_count -= 1;
+}
+
+//Materials
+Ref VoxelMaterialCache::material_get(const int index) {
+ ERR_FAIL_INDEX_V(index, _materials.size(), Ref(NULL));
+
+ return _materials[index];
+}
+
+Ref VoxelMaterialCache::material_lod_get(const int index) {
+ ERR_FAIL_COND_V(_materials.size() == 0, Ref(NULL));
+
+ if (index < 0) {
+ return _materials[0];
+ }
+
+ if (index >= _materials.size()) {
+ return _materials[_materials.size() - 1];
+ }
+
+ return _materials[index];
+}
+
+void VoxelMaterialCache::material_add(const Ref &value) {
+ ERR_FAIL_COND(!value.is_valid());
+
+ _materials.push_back(value);
+}
+
+void VoxelMaterialCache::material_set(const int index, const Ref &value) {
+ ERR_FAIL_INDEX(index, _materials.size());
+
+ _materials.set(index, value);
+}
+
+void VoxelMaterialCache::material_remove(const int index) {
+ _materials.VREMOVE(index);
+}
+
+int VoxelMaterialCache::material_get_num() const {
+ return _materials.size();
+}
+
+void VoxelMaterialCache::materials_clear() {
+ _materials.clear();
+}
+
+Vector VoxelMaterialCache::materials_get() {
+ VARIANT_ARRAY_GET(_materials);
+}
+
+void VoxelMaterialCache::materials_set(const Vector &materials) {
+ _materials.clear();
+
+ for (int i = 0; i < materials.size(); i++) {
+ Ref material = Ref(materials[i]);
+
+ _materials.push_back(material);
+ }
+}
+
+//Surfaces
+Ref VoxelMaterialCache::surface_get(const int index) {
+ ERR_FAIL_INDEX_V(index, _surfaces.size(), Ref());
+
+ return _surfaces[index];
+}
+Ref VoxelMaterialCache::surface_id_get(const int id) {
+ Ref surface;
+
+ for (int i = 0; i < _surfaces.size(); ++i) {
+ surface = _surfaces[i];
+
+ if (surface.is_valid()) {
+ if (surface->get_id() == id) {
+ break;
+ }
+ }
+ }
+
+ return surface;
+}
+void VoxelMaterialCache::surface_add(Ref value) {
+ ERR_FAIL_COND(!value.is_valid());
+
+ _surfaces.push_back(value);
+}
+void VoxelMaterialCache::surface_set(int index, Ref value) {
+ ERR_FAIL_COND(index < 0);
+
+ if (_surfaces.size() < index) {
+ _surfaces.resize(index + 1);
+ }
+
+ _surfaces.set(index, value);
+}
+void VoxelMaterialCache::surface_remove(const int index) {
+ _surfaces.VREMOVE(index);
+}
+int VoxelMaterialCache::surface_get_num() const {
+ return _surfaces.size();
+}
+void VoxelMaterialCache::surfaces_clear() {
+ _surfaces.clear();
+}
+
+void VoxelMaterialCache::additional_texture_add(const Ref &texture) {
+ _additional_textures.push_back(texture);
+}
+void VoxelMaterialCache::additional_texture_remove(const Ref &texture) {
+ for (int i = 0; i < _additional_textures.size(); ++i) {
+ if (_additional_textures[i] == texture) {
+ _additional_textures.VREMOVE(i);
+ return;
+ }
+ }
+}
+void VoxelMaterialCache::additional_texture_remove_index(const int index) {
+ ERR_FAIL_INDEX(index, _additional_textures.size());
+
+ _additional_textures.VREMOVE(index);
+}
+void VoxelMaterialCache::additional_textures_clear() {
+ _additional_textures.clear();
+}
+int VoxelMaterialCache::additional_texture_count() {
+ return _additional_textures.size();
+}
+Ref VoxelMaterialCache::additional_texture_get(const int index) {
+ ERR_FAIL_INDEX_V(index, _additional_textures.size(), Ref());
+
+ return _additional_textures[index];
+}
+Ref VoxelMaterialCache::additional_texture_get_atlas(const int index) {
+ ERR_FAIL_INDEX_V(index, _additional_textures.size(), Ref());
+
+ return additional_texture_get_atlas_tex(_additional_textures[index]);
+}
+Ref VoxelMaterialCache::additional_texture_get_atlas_tex(const Ref &texture) {
+ return Ref();
+}
+Rect2 VoxelMaterialCache::additional_texture_get_uv_rect(const Ref &texture) {
+ return Rect2(0, 0, 1, 1);
+}
+
+#ifdef PROPS_PRESENT
+void VoxelMaterialCache::prop_add_textures(const Ref &prop) {
+ if (!prop.is_valid()) {
+ return;
+ }
+
+ for (int i = 0; i < prop->get_prop_count(); ++i) {
+#if MESH_DATA_RESOURCE_PRESENT
+ Ref pdm = prop->get_prop(i);
+
+ if (pdm.is_valid()) {
+ Ref tex = pdm->get_texture();
+
+ if (!tex.is_valid())
+ continue;
+
+ additional_texture_add(tex);
+ }
+#endif
+
+ Ref pdp = prop->get_prop(i);
+
+ if (pdp.is_valid()) {
+ prop_add_textures(pdp);
+ }
+ }
+}
+void VoxelMaterialCache::prop_remove_textures(const Ref &prop) {
+ if (!prop.is_valid()) {
+ return;
+ }
+
+ for (int i = 0; i < prop->get_prop_count(); ++i) {
+#if MESH_DATA_RESOURCE_PRESENT
+ Ref pdm = prop->get_prop(i);
+
+ if (pdm.is_valid()) {
+ Ref tex = pdm->get_texture();
+
+ if (!tex.is_valid())
+ continue;
+
+ additional_texture_remove(tex);
+ }
+#endif
+
+ Ref pdp = prop->get_prop(i);
+
+ if (pdp.is_valid()) {
+ prop_remove_textures(pdp);
+ }
+ }
+}
+#endif
+
+void VoxelMaterialCache::refresh_rects() {
+ _initialized = true;
+}
+
+void VoxelMaterialCache::setup_material_albedo(Ref texture) {
+#if VERSION_MAJOR < 4
+ if (has_method("_setup_material_albedo")) {
+ call("_setup_material_albedo", texture);
+ }
+#else
+ GDVIRTUAL_CALL(_setup_material_albedo, texture);
+#endif
+}
+
+VoxelMaterialCache::VoxelMaterialCache() {
+ _ref_count = 0;
+ _initialized = false;
+}
+
+VoxelMaterialCache::~VoxelMaterialCache() {
+ _materials.clear();
+ _surfaces.clear();
+}
+
+void VoxelMaterialCache::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_initialized"), &VoxelMaterialCache::get_initialized);
+ ClassDB::bind_method(D_METHOD("set_initialized", "value"), &VoxelMaterialCache::set_initialized);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "initialized"), "set_initialized", "get_initialized");
+
+ ClassDB::bind_method(D_METHOD("get_ref_count"), &VoxelMaterialCache::get_ref_count);
+ ClassDB::bind_method(D_METHOD("set_ref_count", "value"), &VoxelMaterialCache::set_ref_count);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mat_ref_count"), "set_ref_count", "get_ref_count");
+ ClassDB::bind_method(D_METHOD("inc_ref_count"), &VoxelMaterialCache::inc_ref_count);
+ ClassDB::bind_method(D_METHOD("dec_ref_count"), &VoxelMaterialCache::dec_ref_count);
+
+#if VERSION_MAJOR < 4
+ BIND_VMETHOD(MethodInfo("_setup_material_albedo", PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture")));
+#else
+ GDVIRTUAL_BIND(_setup_material_albedo, "texture");
+#endif
+
+ ClassDB::bind_method(D_METHOD("material_get", "index"), &VoxelMaterialCache::material_get);
+ ClassDB::bind_method(D_METHOD("material_lod_get", "index"), &VoxelMaterialCache::material_lod_get);
+ ClassDB::bind_method(D_METHOD("material_add", "value"), &VoxelMaterialCache::material_add);
+ ClassDB::bind_method(D_METHOD("material_set", "index", "value"), &VoxelMaterialCache::material_set);
+ ClassDB::bind_method(D_METHOD("material_remove", "index"), &VoxelMaterialCache::material_remove);
+ ClassDB::bind_method(D_METHOD("material_get_num"), &VoxelMaterialCache::material_get_num);
+ ClassDB::bind_method(D_METHOD("materials_clear"), &VoxelMaterialCache::materials_clear);
+
+ ClassDB::bind_method(D_METHOD("materials_get"), &VoxelMaterialCache::materials_get);
+ ClassDB::bind_method(D_METHOD("materials_set"), &VoxelMaterialCache::materials_set);
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "materials", PROPERTY_HINT_NONE, "17/17:Material", PROPERTY_USAGE_DEFAULT, "Material"), "materials_set", "materials_get");
+
+ ClassDB::bind_method(D_METHOD("surface_get", "index"), &VoxelMaterialCache::surface_get);
+ ClassDB::bind_method(D_METHOD("surface_id_get", "index"), &VoxelMaterialCache::surface_id_get);
+
+ ClassDB::bind_method(D_METHOD("surface_add", "value"), &VoxelMaterialCache::surface_add);
+ ClassDB::bind_method(D_METHOD("surface_set", "index", "surface"), &VoxelMaterialCache::surface_set);
+ ClassDB::bind_method(D_METHOD("surface_remove", "index"), &VoxelMaterialCache::surface_remove);
+ ClassDB::bind_method(D_METHOD("surface_get_num"), &VoxelMaterialCache::surface_get_num);
+ ClassDB::bind_method(D_METHOD("surfaces_clear"), &VoxelMaterialCache::surfaces_clear);
+
+ ClassDB::bind_method(D_METHOD("additional_texture_add", "texture"), &VoxelMaterialCache::additional_texture_add);
+ ClassDB::bind_method(D_METHOD("additional_texture_remove", "texture"), &VoxelMaterialCache::additional_texture_remove);
+ ClassDB::bind_method(D_METHOD("additional_texture_remove_index", "index"), &VoxelMaterialCache::additional_texture_remove_index);
+ ClassDB::bind_method(D_METHOD("additional_textures_clear"), &VoxelMaterialCache::additional_textures_clear);
+ ClassDB::bind_method(D_METHOD("additional_texture_count"), &VoxelMaterialCache::additional_texture_count);
+ ClassDB::bind_method(D_METHOD("additional_texture_get", "index"), &VoxelMaterialCache::additional_texture_get);
+ ClassDB::bind_method(D_METHOD("additional_texture_get_atlas", "index"), &VoxelMaterialCache::additional_texture_get_atlas);
+ ClassDB::bind_method(D_METHOD("additional_texture_get_atlas_tex", "index"), &VoxelMaterialCache::additional_texture_get_atlas_tex);
+ ClassDB::bind_method(D_METHOD("additional_texture_get_uv_rect", "texture"), &VoxelMaterialCache::additional_texture_get_uv_rect);
+
+#ifdef PROPS_PRESENT
+ ClassDB::bind_method(D_METHOD("prop_add_textures", "prop"), &VoxelMaterialCache::prop_add_textures);
+ ClassDB::bind_method(D_METHOD("prop_remove_textures", "prop"), &VoxelMaterialCache::prop_remove_textures);
+#endif
+
+ ClassDB::bind_method(D_METHOD("refresh_rects"), &VoxelMaterialCache::refresh_rects);
+
+ ClassDB::bind_method(D_METHOD("setup_material_albedo", "texture"), &VoxelMaterialCache::setup_material_albedo);
+}
diff --git a/library/voxel_material_cache.h b/library/voxel_material_cache.h
new file mode 100644
index 0000000..98773c7
--- /dev/null
+++ b/library/voxel_material_cache.h
@@ -0,0 +1,116 @@
+/*
+Copyright (c) 2019-2022 Péter Magyar
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef VOXEL_MATERIAL_CACHE_H
+#define VOXEL_MATERIAL_CACHE_H
+
+#include "core/version.h"
+
+#if VERSION_MAJOR > 3
+#include "core/io/resource.h"
+#include "core/math/color.h"
+#include "core/templates/vector.h"
+#else
+#include "core/color.h"
+#include "core/resource.h"
+#include "core/vector.h"
+#endif
+
+#include "core/math/rect2.h"
+#include "scene/resources/material.h"
+
+#include "voxel_library.h"
+
+#include "../defines.h"
+
+class VoxelLibrary;
+
+class VoxelMaterialCache : public Resource {
+ GDCLASS(VoxelMaterialCache, Resource)
+
+public:
+ bool get_initialized();
+ void set_initialized(const bool value);
+
+ int get_ref_count();
+ void set_ref_count(const int value);
+ void inc_ref_count();
+ void dec_ref_count();
+
+ Ref material_get(const int index);
+ Ref material_lod_get(const int index);
+ void material_add(const Ref &value);
+ void material_set(const int index, const Ref &value);
+ void material_remove(const int index);
+ int material_get_num() const;
+ void materials_clear();
+
+ Vector materials_get();
+ void materials_set(const Vector &materials);
+
+ virtual Ref surface_get(const int index);
+ virtual Ref surface_id_get(const int id);
+ virtual void surface_add(Ref value);
+ virtual void surface_set(const int index, Ref value);
+ virtual void surface_remove(const int index);
+ virtual int surface_get_num() const;
+ virtual void surfaces_clear();
+
+ virtual void additional_texture_add(const Ref &texture);
+ virtual void additional_texture_remove(const Ref &texture);
+ virtual void additional_texture_remove_index(const int index);
+ virtual void additional_textures_clear();
+ virtual int additional_texture_count();
+ virtual Ref additional_texture_get(const int index);
+ virtual Ref additional_texture_get_atlas(const int index);
+ virtual Ref additional_texture_get_atlas_tex(const Ref &texture);
+ virtual Rect2 additional_texture_get_uv_rect(const Ref &texture);
+
+#ifdef PROPS_PRESENT
+ void prop_add_textures(const Ref &prop);
+ void prop_remove_textures(const Ref &prop);
+#endif
+
+ virtual void refresh_rects();
+
+ void setup_material_albedo(Ref texture);
+
+#if VERSION_MAJOR >= 4
+ GDVIRTUAL1(_setup_material_albedo, Ref);
+#endif
+
+ VoxelMaterialCache();
+ ~VoxelMaterialCache();
+
+protected:
+ static void _bind_methods();
+
+ bool _initialized;
+
+ Vector][> _surfaces;
+ Vector][> _materials;
+ Vector][> _additional_textures;
+
+ int _ref_count;
+};
+
+#endif
diff --git a/library/voxel_material_cache_pcm.cpp b/library/voxel_material_cache_pcm.cpp
new file mode 100644
index 0000000..c64c2bc
--- /dev/null
+++ b/library/voxel_material_cache_pcm.cpp
@@ -0,0 +1,232 @@
+/*
+Copyright (c) 2019-2022 Péter Magyar
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include "voxel_material_cache_pcm.h"
+
+#include "../../texture_packer/texture_packer.h"
+#include "scene/resources/texture.h"
+#include "voxel_surface.h"
+#include "voxel_surface_merger.h"
+
+int VoxelMaterialCachePCM::get_texture_flags() const {
+ return _packer->get_texture_flags();
+}
+void VoxelMaterialCachePCM::set_texture_flags(const int flags) {
+ _packer->set_texture_flags(flags);
+}
+
+int VoxelMaterialCachePCM::get_max_atlas_size() const {
+ return _packer->get_max_atlas_size();
+}
+void VoxelMaterialCachePCM::set_max_atlas_size(const int size) {
+ _packer->set_max_atlas_size(size);
+}
+
+bool VoxelMaterialCachePCM::get_keep_original_atlases() const {
+ return _packer->get_keep_original_atlases();
+}
+void VoxelMaterialCachePCM::set_keep_original_atlases(const bool value) {
+ _packer->set_keep_original_atlases(value);
+}
+
+Color VoxelMaterialCachePCM::get_background_color() const {
+ return _packer->get_background_color();
+}
+void VoxelMaterialCachePCM::set_background_color(const Color &color) {
+ _packer->set_background_color(color);
+}
+
+int VoxelMaterialCachePCM::get_margin() const {
+ return _packer->get_margin();
+}
+void VoxelMaterialCachePCM::set_margin(const int margin) {
+ _packer->set_margin(margin);
+}
+
+Ref VoxelMaterialCachePCM::additional_texture_get_atlas_tex(const Ref &texture) {
+ if (!_packer->contains_texture(texture)) {
+ return Ref();
+ }
+
+ return _packer->get_texture(texture);
+}
+Rect2 VoxelMaterialCachePCM::additional_texture_get_uv_rect(const Ref &texture) {
+ if (!texture.is_valid()) {
+ return Rect2(0, 0, 1, 1);
+ }
+
+ Ref at = _packer->get_texture(texture);
+
+ if (!at.is_valid()) {
+ return Rect2(0, 0, 1, 1);
+ }
+
+ Rect2 region = at->get_region();
+
+ Ref tex = at->get_atlas();
+
+ if (!tex.is_valid()) {
+ return Rect2(0, 0, 1, 1);
+ }
+
+ Ref image = tex->get_data();
+
+ if (!image.is_valid()) {
+ return Rect2(0, 0, 1, 1);
+ }
+
+ float w = image->get_width();
+ float h = image->get_height();
+
+ region.position = Size2(region.position.x / w, region.position.y / h);
+ region.size = Size2(region.size.x / w, region.size.y / h);
+
+ return region;
+}
+
+void VoxelMaterialCachePCM::refresh_rects() {
+ bool texture_added = false;
+ for (int i = 0; i < _surfaces.size(); i++) {
+ Ref surface = Ref(_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));
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < _additional_textures.size(); i++) {
+ Ref tex = _additional_textures.get(i);
+
+ ERR_CONTINUE(!tex.is_valid());
+
+ if (!_packer->contains_texture(tex)) {
+ _packer->add_texture(tex);
+ texture_added = true;
+ }
+ }
+
+ if (texture_added) {
+ _packer->merge();
+
+ ERR_FAIL_COND(_packer->get_texture_count() == 0);
+
+ Ref tex = _packer->get_generated_texture(0);
+
+ setup_material_albedo(tex);
+ }
+
+ for (int i = 0; i < _surfaces.size(); i++) {
+ Ref surface = _surfaces[i];
+
+ if (surface.is_valid()) {
+ surface->refresh_rects();
+ }
+ }
+
+ _initialized = true;
+}
+
+void VoxelMaterialCachePCM::_setup_material_albedo(Ref texture) {
+ int count = material_get_num();
+
+ for (int i = 0; i < count; ++i) {
+ Ref m = material_get(i);
+
+ Ref spmat = m;
+
+ if (spmat.is_valid()) {
+ spmat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture);
+ return;
+ }
+
+ Ref shmat = m;
+
+ if (shmat.is_valid()) {
+ shmat->set_shader_param("texture_albedo", texture);
+ }
+ }
+}
+
+VoxelMaterialCachePCM::VoxelMaterialCachePCM() {
+ _packer.instance();
+
+#if GODOT4
+#warning implement
+#else
+ _packer->set_texture_flags(Texture::FLAG_MIPMAPS | Texture::FLAG_FILTER);
+#endif
+
+ _packer->set_max_atlas_size(1024);
+ _packer->set_keep_original_atlases(false);
+ _packer->set_margin(0);
+}
+
+VoxelMaterialCachePCM::~VoxelMaterialCachePCM() {
+ for (int i = 0; i < _surfaces.size(); ++i) {
+ Ref surface = _surfaces[i];
+
+ if (surface.is_valid()) {
+ surface->set_library(Ref());
+ }
+ }
+
+ _surfaces.clear();
+
+ _packer->clear();
+ _packer.unref();
+}
+
+void VoxelMaterialCachePCM::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_texture_flags"), &VoxelMaterialCachePCM::get_texture_flags);
+ ClassDB::bind_method(D_METHOD("set_texture_flags", "flags"), &VoxelMaterialCachePCM::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_max_atlas_size"), &VoxelMaterialCachePCM::get_max_atlas_size);
+ ClassDB::bind_method(D_METHOD("set_max_atlas_size", "size"), &VoxelMaterialCachePCM::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"), &VoxelMaterialCachePCM::get_keep_original_atlases);
+ ClassDB::bind_method(D_METHOD("set_keep_original_atlases", "value"), &VoxelMaterialCachePCM::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"), &VoxelMaterialCachePCM::get_background_color);
+ ClassDB::bind_method(D_METHOD("set_background_color", "color"), &VoxelMaterialCachePCM::set_background_color);
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_background_color", "get_background_color");
+
+ ClassDB::bind_method(D_METHOD("get_margin"), &VoxelMaterialCachePCM::get_margin);
+ ClassDB::bind_method(D_METHOD("set_margin", "size"), &VoxelMaterialCachePCM::set_margin);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "margin"), "set_margin", "get_margin");
+
+ ClassDB::bind_method(D_METHOD("_setup_material_albedo", "texture"), &VoxelMaterialCachePCM::_setup_material_albedo);
+}
diff --git a/library/voxel_material_cache_pcm.h b/library/voxel_material_cache_pcm.h
new file mode 100644
index 0000000..70e850e
--- /dev/null
+++ b/library/voxel_material_cache_pcm.h
@@ -0,0 +1,84 @@
+/*
+Copyright (c) 2019-2022 Péter Magyar
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef VOXEL_MATERIAL_CACHE_PCM_H
+#define VOXEL_MATERIAL_CACHE_PCM_H
+
+#include "voxel_material_cache.h"
+
+#include "core/version.h"
+
+#if VERSION_MAJOR > 3
+#include "core/io/resource.h"
+#include "core/math/color.h"
+#include "core/templates/vector.h"
+#else
+#include "core/color.h"
+#include "core/resource.h"
+#include "core/vector.h"
+#endif
+
+#include "core/math/rect2.h"
+#include "scene/resources/material.h"
+
+#include "../defines.h"
+
+class VoxelSurface;
+class TexturePacker;
+class PropData;
+
+class VoxelMaterialCachePCM : public VoxelMaterialCache {
+ GDCLASS(VoxelMaterialCachePCM, VoxelMaterialCache);
+
+public:
+ int get_texture_flags() const;
+ void set_texture_flags(const int flags);
+
+ 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 additional_texture_get_atlas_tex(const Ref &texture);
+ Rect2 additional_texture_get_uv_rect(const Ref &texture);
+
+ void refresh_rects();
+
+ void _setup_material_albedo(Ref texture);
+
+ VoxelMaterialCachePCM();
+ ~VoxelMaterialCachePCM();
+
+protected:
+ static void _bind_methods();
+
+ Ref _packer;
+};
+
+#endif
diff --git a/register_types.cpp b/register_types.cpp
index 7e0fbb6..3d78d65 100644
--- a/register_types.cpp
+++ b/register_types.cpp
@@ -27,10 +27,13 @@ SOFTWARE.
#include "library/voxel_library.h"
#include "library/voxel_library_simple.h"
+#include "library/voxel_material_cache.h"
#ifdef TEXTURE_PACKER_PRESENT
-#include "library/voxel_surface_merger.h"
#include "library/voxel_library_merger.h"
+#include "library/voxel_library_merger_pcm.h"
+#include "library/voxel_material_cache_pcm.h"
+#include "library/voxel_surface_merger.h"
#endif
#include "data/voxel_light.h"
@@ -90,9 +93,13 @@ void register_voxelman_types() {
ClassDB::register_class();
ClassDB::register_class();
+ ClassDB::register_class();
+
#ifdef TEXTURE_PACKER_PRESENT
ClassDB::register_class();
ClassDB::register_class();
+ ClassDB::register_class();
+ ClassDB::register_class();
#endif
ClassDB::register_class();
diff --git a/world/voxel_chunk.cpp b/world/voxel_chunk.cpp
index e5351a6..a24948d 100644
--- a/world/voxel_chunk.cpp
+++ b/world/voxel_chunk.cpp
@@ -188,6 +188,48 @@ _FORCE_INLINE_ void VoxelChunk::set_margin_end(const int value) {
_margin_end = value;
}
+int VoxelChunk::material_cache_key_get() const {
+ return _material_cache_key;
+}
+void VoxelChunk::material_cache_key_set(const int value) {
+ _material_cache_key = value;
+}
+
+bool VoxelChunk::material_cache_key_has() const {
+ return _material_cache_key_has;
+}
+void VoxelChunk::material_cache_key_has_set(const bool value) {
+ _material_cache_key_has = value;
+}
+
+int VoxelChunk::liquid_material_cache_key_get() const {
+ return _liquid_material_cache_key;
+}
+void VoxelChunk::liquid_material_cache_key_set(const int value) {
+ _liquid_material_cache_key = value;
+}
+
+bool VoxelChunk::liquid_material_cache_key_has() const {
+ return _liquid_material_cache_key_has;
+}
+void VoxelChunk::liquid_material_cache_key_has_set(const bool value) {
+ _liquid_material_cache_key_has = value;
+}
+
+int VoxelChunk::prop_material_cache_key_get() const {
+ return _prop_material_cache_key;
+}
+void VoxelChunk::prop_material_cache_key_set(const int value) {
+ _prop_material_cache_key = value;
+}
+
+bool VoxelChunk::prop_material_cache_key_has() const {
+ return _prop_material_cache_key_has;
+}
+void VoxelChunk::prop_material_cache_key_has_set(const bool value) {
+ _prop_material_cache_key_has = value;
+}
+
Ref VoxelChunk::get_library() {
return _library;
}
@@ -1137,6 +1179,15 @@ VoxelChunk::VoxelChunk() {
_margin_start = 0;
_margin_end = 0;
+ _material_cache_key = 0;
+ _material_cache_key_has = false;
+
+ _liquid_material_cache_key = 0;
+ _liquid_material_cache_key_has = false;
+
+ _prop_material_cache_key = 0;
+ _prop_material_cache_key_has = false;
+
_current_job = -1;
_queued_generation = false;
@@ -1456,6 +1507,30 @@ void VoxelChunk::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_margin_end"), &VoxelChunk::set_margin_end);
ADD_PROPERTY(PropertyInfo(Variant::INT, "margin_end"), "set_margin_end", "get_margin_end");
+ ClassDB::bind_method(D_METHOD("material_cache_key_get"), &VoxelChunk::material_cache_key_get);
+ ClassDB::bind_method(D_METHOD("material_cache_key_set"), &VoxelChunk::material_cache_key_set);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "material_cache_key"), "material_cache_key_set", "material_cache_key_get");
+
+ ClassDB::bind_method(D_METHOD("material_cache_key_has"), &VoxelChunk::material_cache_key_has);
+ ClassDB::bind_method(D_METHOD("material_cache_key_has_set"), &VoxelChunk::material_cache_key_has_set);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "material_cache_key_has"), "material_cache_key_has_set", "material_cache_key_has");
+
+ ClassDB::bind_method(D_METHOD("liquid_material_cache_key_get"), &VoxelChunk::liquid_material_cache_key_get);
+ ClassDB::bind_method(D_METHOD("liquid_material_cache_key_set"), &VoxelChunk::liquid_material_cache_key_set);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "liquid_material_cache_key"), "liquid_material_cache_key_set", "liquid_material_cache_key_get");
+
+ ClassDB::bind_method(D_METHOD("liquid_material_cache_key_has"), &VoxelChunk::liquid_material_cache_key_has);
+ ClassDB::bind_method(D_METHOD("liquid_material_cache_key_has_set"), &VoxelChunk::liquid_material_cache_key_has_set);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "liquid_material_cache_key_has"), "liquid_material_cache_key_has_set", "liquid_material_cache_key_has");
+
+ ClassDB::bind_method(D_METHOD("prop_material_cache_key_get"), &VoxelChunk::prop_material_cache_key_get);
+ ClassDB::bind_method(D_METHOD("prop_material_cache_key_set"), &VoxelChunk::prop_material_cache_key_set);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "prop_material_cache_key"), "prop_material_cache_key_set", "prop_material_cache_key_get");
+
+ ClassDB::bind_method(D_METHOD("prop_material_cache_key_has"), &VoxelChunk::prop_material_cache_key_has);
+ ClassDB::bind_method(D_METHOD("prop_material_cache_key_has_set"), &VoxelChunk::prop_material_cache_key_has_set);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "prop_material_cache_key_has"), "prop_material_cache_key_has_set", "prop_material_cache_key_has");
+
ClassDB::bind_method(D_METHOD("get_library"), &VoxelChunk::get_library);
ClassDB::bind_method(D_METHOD("set_library", "value"), &VoxelChunk::set_library);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "library", PROPERTY_HINT_RESOURCE_TYPE, "VoxelLibrary"), "set_library", "get_library");
diff --git a/world/voxel_chunk.h b/world/voxel_chunk.h
index bfd7e9d..dd51360 100644
--- a/world/voxel_chunk.h
+++ b/world/voxel_chunk.h
@@ -67,8 +67,8 @@ include_pool_vector
typedef class Transform3D Transform;
#endif
-#include "../library/voxel_surface.h"
#include "../library/voxel_library.h"
+#include "../library/voxel_surface.h"
; //hackfix for a clang format issue
class VoxelJob;
@@ -144,6 +144,24 @@ public:
void set_margin_start(const int value);
void set_margin_end(const int value);
+ int material_cache_key_get() const;
+ void material_cache_key_set(const int value);
+
+ bool material_cache_key_has() const;
+ void material_cache_key_has_set(const bool value);
+
+ int liquid_material_cache_key_get() const;
+ void liquid_material_cache_key_set(const int value);
+
+ bool liquid_material_cache_key_has() const;
+ void liquid_material_cache_key_has_set(const bool value);
+
+ int prop_material_cache_key_get() const;
+ void prop_material_cache_key_set(const int value);
+
+ bool prop_material_cache_key_has() const;
+ void prop_material_cache_key_has_set(const bool value);
+
Ref get_library();
void set_library(const Ref &value);
@@ -395,6 +413,15 @@ protected:
int _margin_start;
int _margin_end;
+ int _material_cache_key;
+ bool _material_cache_key_has;
+
+ int _liquid_material_cache_key;
+ bool _liquid_material_cache_key_has;
+
+ int _prop_material_cache_key;
+ bool _prop_material_cache_key_has;
+
Vector _channels;
float _voxel_scale;
]