From 3b7eb818e30d22a61820f2b8c1362677fb890d29 Mon Sep 17 00:00:00 2001 From: The Tophat Demon Date: Mon, 4 Oct 2021 10:49:42 -0500 Subject: [PATCH] GLTF imports & exports material texture filters --- editor_modules/gltf/config.py | 1 + editor_modules/gltf/doc_classes/GLTFState.xml | 13 ++ .../gltf/doc_classes/GLTFTexture.xml | 3 + editor_modules/gltf/gltf_document.cpp | 180 +++++++++++++++--- editor_modules/gltf/gltf_document.h | 8 + editor_modules/gltf/gltf_state.cpp | 11 ++ editor_modules/gltf/gltf_state.h | 11 +- editor_modules/gltf/gltf_texture.cpp | 11 ++ editor_modules/gltf/gltf_texture.h | 3 + editor_modules/gltf/register_types.cpp | 1 + .../gltf/doc_classes/GLTFTextureSampler.xml | 29 +++ modules/gltf/gltf_texture_sampler.cpp | 47 +++++ modules/gltf/gltf_texture_sampler.h | 165 ++++++++++++++++ 13 files changed, 454 insertions(+), 29 deletions(-) create mode 100644 modules/gltf/doc_classes/GLTFTextureSampler.xml create mode 100644 modules/gltf/gltf_texture_sampler.cpp create mode 100644 modules/gltf/gltf_texture_sampler.h diff --git a/editor_modules/gltf/config.py b/editor_modules/gltf/config.py index a4ee871ef..41b76769b 100644 --- a/editor_modules/gltf/config.py +++ b/editor_modules/gltf/config.py @@ -22,6 +22,7 @@ def get_doc_classes(): "GLTFSpecGloss", "GLTFState", "GLTFTexture", + "GLTFTextureSampler", "PackedSceneGLTF", ] diff --git a/editor_modules/gltf/doc_classes/GLTFState.xml b/editor_modules/gltf/doc_classes/GLTFState.xml index 71621841b..80cd8ce7c 100644 --- a/editor_modules/gltf/doc_classes/GLTFState.xml +++ b/editor_modules/gltf/doc_classes/GLTFState.xml @@ -86,6 +86,12 @@ + + + + Retrieves the array of texture samplers that are used by the textures contained in the GLTF. + + @@ -173,6 +179,13 @@ + + + + + Sets the array of texture samplers that are used by the textures contained in the GLTF. + + diff --git a/editor_modules/gltf/doc_classes/GLTFTexture.xml b/editor_modules/gltf/doc_classes/GLTFTexture.xml index 767626300..08d09f110 100644 --- a/editor_modules/gltf/doc_classes/GLTFTexture.xml +++ b/editor_modules/gltf/doc_classes/GLTFTexture.xml @@ -10,6 +10,9 @@ + + ID of the texture sampler to use when sampling the image. If -1, then the default texture sampler is used (linear filtering, and repeat wrapping in both axes). + diff --git a/editor_modules/gltf/gltf_document.cpp b/editor_modules/gltf/gltf_document.cpp index 7dfa42bef..4a617c2f9 100644 --- a/editor_modules/gltf/gltf_document.cpp +++ b/editor_modules/gltf/gltf_document.cpp @@ -135,71 +135,71 @@ Error GLTFDocument::serialize(Ref state, Node *p_root, const String & return Error::FAILED; } - /* STEP 7 SERIALIZE ANIMATIONS */ + /* STEP 7 SERIALIZE TEXTURE SAMPLERS */ + err = _serialize_texture_samplers(state); + if (err != OK) { + return Error::FAILED; + } + + /* STEP 8 SERIALIZE ANIMATIONS */ err = _serialize_animations(state); if (err != OK) { return Error::FAILED; } - /* STEP 8 SERIALIZE ACCESSORS */ + /* STEP 9 SERIALIZE ACCESSORS */ err = _encode_accessors(state); if (err != OK) { return Error::FAILED; } - /* STEP 9 SERIALIZE IMAGES */ + /* STEP 10 SERIALIZE IMAGES */ err = _serialize_images(state, p_path); if (err != OK) { return Error::FAILED; } - /* STEP 10 SERIALIZE TEXTURES */ - err = _serialize_textures(state); - if (err != OK) { - return Error::FAILED; - } - for (GLTFBufferViewIndex i = 0; i < state->buffer_views.size(); i++) { state->buffer_views.write[i]->buffer = 0; } - /* STEP 11 SERIALIZE BUFFER VIEWS */ + /* STEP 12 SERIALIZE BUFFER VIEWS */ err = _encode_buffer_views(state); if (err != OK) { return Error::FAILED; } - /* STEP 12 SERIALIZE NODES */ + /* STEP 13 SERIALIZE NODES */ err = _serialize_nodes(state); if (err != OK) { return Error::FAILED; } - /* STEP 13 SERIALIZE SCENE */ + /* STEP 15 SERIALIZE SCENE */ err = _serialize_scenes(state); if (err != OK) { return Error::FAILED; } - /* STEP 14 SERIALIZE SCENE */ + /* STEP 16 SERIALIZE SCENE */ err = _serialize_lights(state); if (err != OK) { return Error::FAILED; } - /* STEP 15 SERIALIZE EXTENSIONS */ + /* STEP 17 SERIALIZE EXTENSIONS */ err = _serialize_extensions(state); if (err != OK) { return Error::FAILED; } - /* STEP 16 SERIALIZE VERSION */ + /* STEP 18 SERIALIZE VERSION */ err = _serialize_version(state); if (err != OK) { return Error::FAILED; } - /* STEP 17 SERIALIZE FILE */ + /* STEP 19 SERIALIZE FILE */ err = _serialize_file(state, p_path); if (err != OK) { return Error::FAILED; @@ -2950,7 +2950,7 @@ Error GLTFDocument::_serialize_images(Ref state, const String &p_path ERR_CONTINUE(state->images[i].is_null()); - Ref image = state->images[i]->get_data(); + Ref image = state->images[i]; ERR_CONTINUE(image.is_null()); if (p_path.to_lower().ends_with("glb")) { @@ -3155,11 +3155,7 @@ Error GLTFDocument::_parse_images(Ref state, const String &p_base_pat continue; } - Ref t; - t.instance(); - t->create_from_image(img); - - state->images.push_back(t); + state->images.push_back(img); } print_verbose("glTF: Total images: " + itos(state->images.size())); @@ -3178,6 +3174,11 @@ Error GLTFDocument::_serialize_textures(Ref state) { Ref t = state->textures[i]; ERR_CONTINUE(t->get_src_image() == -1); d["source"] = t->get_src_image(); + + GLTFTextureSamplerIndex sampler_index = t->get_sampler(); + if (sampler_index != -1) { + d["sampler"] = sampler_index; + } textures.push_back(d); } state->json["textures"] = textures; @@ -3199,7 +3200,24 @@ Error GLTFDocument::_parse_textures(Ref state) { Ref t; t.instance(); t->set_src_image(d["source"]); + if (d.has("sampler")) { + t->set_sampler(d["sampler"]); + } else { + t->set_sampler(-1); + } state->textures.push_back(t); + + // Create and cache the texture used in the engine + Ref imgTex; + imgTex.instance(); + imgTex->create_from_image(state->images[t->get_src_image()]); + + // Set texture filter and repeat based on sampler settings + const Ref sampler = _get_sampler_for_texture(state, t->get_sampler()); + Texture::Flags flags = sampler->get_texture_flags(); + imgTex->set_flags(flags); + + state->texture_cache.insert(i, imgTex); } return OK; @@ -3207,24 +3225,124 @@ Error GLTFDocument::_parse_textures(Ref state) { GLTFTextureIndex GLTFDocument::_set_texture(Ref state, Ref p_texture) { ERR_FAIL_COND_V(p_texture.is_null(), -1); + ERR_FAIL_COND_V(p_texture->get_data().is_null(), -1); + + // Create GLTF data structures for the new texture Ref gltf_texture; gltf_texture.instance(); - ERR_FAIL_COND_V(p_texture->get_data().is_null(), -1); GLTFImageIndex gltf_src_image_i = state->images.size(); - state->images.push_back(p_texture); + + state->images.push_back(p_texture->get_data()); + + GLTFTextureSamplerIndex gltf_sampler_i = _set_sampler_for_mode(state, p_texture->get_flags()); + gltf_texture->set_src_image(gltf_src_image_i); + gltf_texture->set_sampler(gltf_sampler_i); + GLTFTextureIndex gltf_texture_i = state->textures.size(); state->textures.push_back(gltf_texture); + state->texture_cache[gltf_texture_i] = p_texture; return gltf_texture_i; } Ref GLTFDocument::_get_texture(Ref state, const GLTFTextureIndex p_texture) { ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref()); - const GLTFImageIndex image = state->textures[p_texture]->get_src_image(); + return state->texture_cache[p_texture]; +} - ERR_FAIL_INDEX_V(image, state->images.size(), Ref()); +GLTFTextureSamplerIndex GLTFDocument::_set_sampler_for_mode(Ref state, uint32_t p_mode) { + for (int i = 0; i < state->texture_samplers.size(); ++i) { + if (state->texture_samplers[i]->get_texture_flags() == p_mode) { + return i; + } + } - return state->images[image]; + GLTFTextureSamplerIndex gltf_sampler_i = state->texture_samplers.size(); + Ref gltf_sampler; + gltf_sampler.instance(); + gltf_sampler->set_texture_flags(p_mode); + state->texture_samplers.push_back(gltf_sampler); + return gltf_sampler_i; +} + +Ref GLTFDocument::_get_sampler_for_texture(Ref state, const GLTFTextureIndex p_texture) { + ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref()); + const GLTFTextureSamplerIndex sampler = state->textures[p_texture]->get_sampler(); + + if (sampler == -1) { + return state->default_texture_sampler; + } else { + ERR_FAIL_INDEX_V(sampler, state->texture_samplers.size(), Ref()); + + return state->texture_samplers[sampler]; + } +} + +Error GLTFDocument::_serialize_texture_samplers(Ref state) { + if (!state->texture_samplers.size()) { + return OK; + } + + Array samplers; + for (int32_t i = 0; i < state->texture_samplers.size(); ++i) { + Dictionary d; + Ref s = state->texture_samplers[i]; + d["magFilter"] = s->get_mag_filter(); + d["minFilter"] = s->get_min_filter(); + d["wrapS"] = s->get_wrap_s(); + d["wrapT"] = s->get_wrap_t(); + samplers.push_back(d); + } + state->json["samplers"] = samplers; + + return OK; +} + +Error GLTFDocument::_parse_texture_samplers(Ref state) { + state->default_texture_sampler.instance(); + state->default_texture_sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR); + state->default_texture_sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR); + state->default_texture_sampler->set_wrap_s(GLTFTextureSampler::WrapMode::REPEAT); + state->default_texture_sampler->set_wrap_t(GLTFTextureSampler::WrapMode::REPEAT); + + if (!state->json.has("samplers")) { + return OK; + } + + const Array &samplers = state->json["samplers"]; + for (int i = 0; i < samplers.size(); ++i) { + const Dictionary &d = samplers[i]; + + Ref sampler; + sampler.instance(); + + if (d.has("minFilter")) { + sampler->set_min_filter(d["minFilter"]); + } else { + sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR); + } + if (d.has("magFilter")) { + sampler->set_mag_filter(d["magFilter"]); + } else { + sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR); + } + + if (d.has("wrapS")) { + sampler->set_wrap_s(d["wrapS"]); + } else { + sampler->set_wrap_s(GLTFTextureSampler::WrapMode::REPEAT); + } + + if (d.has("wrapT")) { + sampler->set_wrap_t(d["wrapT"]); + } else { + sampler->set_wrap_t(GLTFTextureSampler::WrapMode::REPEAT); + } + + state->texture_samplers.push_back(sampler); + } + + return OK; } Error GLTFDocument::_serialize_materials(Ref state) { @@ -6668,13 +6786,19 @@ Error GLTFDocument::parse(Ref state, String p_path, bool p_read_binar return Error::FAILED; } + /* PARSE TEXTURE SAMPLERS */ + err = _parse_texture_samplers(state); + if (err != OK) { + return Error::FAILED; + } + /* PARSE TEXTURES */ err = _parse_textures(state); if (err != OK) { return Error::FAILED; } - /* PARSE TEXTURES */ + /* PARSE MATERIALS */ err = _parse_materials(state); if (err != OK) { return Error::FAILED; diff --git a/editor_modules/gltf/gltf_document.h b/editor_modules/gltf/gltf_document.h index 5c882969f..ba7b4e651 100644 --- a/editor_modules/gltf/gltf_document.h +++ b/editor_modules/gltf/gltf_document.h @@ -52,6 +52,7 @@ class GLTFSkin; class GLTFNode; class GLTFSpecGloss; class GLTFSkeleton; +class GLTFTextureSampler; class MultiMeshInstance; using GLTFAccessorIndex = int; @@ -67,6 +68,7 @@ using GLTFNodeIndex = int; using GLTFSkeletonIndex = int; using GLTFSkinIndex = int; using GLTFTextureIndex = int; +using GLTFTextureSamplerIndex = int; class GLTFDocument : public Resource { GDCLASS(GLTFDocument, Resource); @@ -178,6 +180,10 @@ private: GLTFTextureIndex _set_texture(Ref state, Ref p_texture); Ref _get_texture(Ref state, const GLTFTextureIndex p_texture); + GLTFTextureSamplerIndex _set_sampler_for_mode(Ref state, + uint32_t p_mode); + Ref _get_sampler_for_texture(Ref state, + const GLTFTextureIndex p_texture); Error _parse_json(const String &p_path, Ref state); Error _parse_glb(const String &p_path, Ref state); void _compute_node_heights(Ref state); @@ -225,10 +231,12 @@ private: const bool p_for_vertex); Error _parse_meshes(Ref state); Error _serialize_textures(Ref state); + Error _serialize_texture_samplers(Ref state); Error _serialize_images(Ref state, const String &p_path); Error _serialize_lights(Ref state); Error _parse_images(Ref state, const String &p_base_path); Error _parse_textures(Ref state); + Error _parse_texture_samplers(Ref state); Error _parse_materials(Ref state); void _set_texture_transform_uv1(const Dictionary &d, Ref material); void spec_gloss_to_rough_metal(Ref r_spec_gloss, diff --git a/editor_modules/gltf/gltf_state.cpp b/editor_modules/gltf/gltf_state.cpp index 7c9818b94..46579b61f 100644 --- a/editor_modules/gltf/gltf_state.cpp +++ b/editor_modules/gltf/gltf_state.cpp @@ -61,6 +61,8 @@ void GLTFState::_bind_methods() { ClassDB::bind_method(D_METHOD("set_root_nodes", "root_nodes"), &GLTFState::set_root_nodes); ClassDB::bind_method(D_METHOD("get_textures"), &GLTFState::get_textures); ClassDB::bind_method(D_METHOD("set_textures", "textures"), &GLTFState::set_textures); + ClassDB::bind_method(D_METHOD("get_texture_samplers"), &GLTFState::get_texture_samplers); + ClassDB::bind_method(D_METHOD("set_texture_samplers", "texture_samplers"), &GLTFState::set_texture_samplers); ClassDB::bind_method(D_METHOD("get_images"), &GLTFState::get_images); ClassDB::bind_method(D_METHOD("set_images", "images"), &GLTFState::set_images); ClassDB::bind_method(D_METHOD("get_skins"), &GLTFState::get_skins); @@ -95,6 +97,7 @@ void GLTFState::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "scene_name"), "set_scene_name", "get_scene_name"); // String ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "root_nodes"), "set_root_nodes", "get_root_nodes"); // Vector ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_textures", "get_textures"); // Vector> + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "texture_samplers", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_texture_samplers", "get_texture_samplers"); //Vector> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "images", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_images", "get_images"); // Vector ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skins", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skins", "get_skins"); // Vector> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "cameras", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_cameras", "get_cameras"); // Vector> @@ -218,6 +221,14 @@ void GLTFState::set_textures(Array p_textures) { GLTFDocument::set_from_array(textures, p_textures); } +Array GLTFState::get_texture_samplers() { + return GLTFDocument::to_array(texture_samplers); +} + +void GLTFState::set_texture_samplers(Array p_texture_samplers) { + GLTFDocument::set_from_array(texture_samplers, p_texture_samplers); +} + Array GLTFState::get_images() { return GLTFDocument::to_array(images); } diff --git a/editor_modules/gltf/gltf_state.h b/editor_modules/gltf/gltf_state.h index fd4411c82..94a20b061 100644 --- a/editor_modules/gltf/gltf_state.h +++ b/editor_modules/gltf/gltf_state.h @@ -47,6 +47,9 @@ #include "gltf_skeleton.h" #include "gltf_skin.h" #include "gltf_texture.h" +#include "gltf_texture_sampler.h" +#include "scene/animation/animation_player.h" +#include "scene/resources/texture.h" class GLTFState : public Resource { GDCLASS(GLTFState, Resource); @@ -77,7 +80,10 @@ class GLTFState : public Resource { String scene_name; Vector root_nodes; Vector> textures; - Vector> images; + Vector> texture_samplers; + Ref default_texture_sampler; + Vector> images; + Map> texture_cache; Vector> skins; Vector> cameras; @@ -139,6 +145,9 @@ public: Array get_textures(); void set_textures(Array p_textures); + Array get_texture_samplers(); + void set_texture_samplers(Array p_texture_samplers); + Array get_images(); void set_images(Array p_images); diff --git a/editor_modules/gltf/gltf_texture.cpp b/editor_modules/gltf/gltf_texture.cpp index 2a21cb3df..5cc96e322 100644 --- a/editor_modules/gltf/gltf_texture.cpp +++ b/editor_modules/gltf/gltf_texture.cpp @@ -33,8 +33,11 @@ void GLTFTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("get_src_image"), &GLTFTexture::get_src_image); ClassDB::bind_method(D_METHOD("set_src_image", "src_image"), &GLTFTexture::set_src_image); + ClassDB::bind_method(D_METHOD("get_sampler"), &GLTFTexture::get_sampler); + ClassDB::bind_method(D_METHOD("set_sampler", "sampler"), &GLTFTexture::set_sampler); ADD_PROPERTY(PropertyInfo(Variant::INT, "src_image"), "set_src_image", "get_src_image"); // int + ADD_PROPERTY(PropertyInfo(Variant::INT, "sampler"), "set_sampler", "get_sampler"); // int } GLTFImageIndex GLTFTexture::get_src_image() const { @@ -44,3 +47,11 @@ GLTFImageIndex GLTFTexture::get_src_image() const { void GLTFTexture::set_src_image(GLTFImageIndex val) { src_image = val; } + +GLTFTextureSamplerIndex GLTFTexture::get_sampler() const { + return sampler; +} + +void GLTFTexture::set_sampler(GLTFTextureSamplerIndex val) { + sampler = val; +} diff --git a/editor_modules/gltf/gltf_texture.h b/editor_modules/gltf/gltf_texture.h index 886777c1b..82e5d5dd1 100644 --- a/editor_modules/gltf/gltf_texture.h +++ b/editor_modules/gltf/gltf_texture.h @@ -39,6 +39,7 @@ class GLTFTexture : public Resource { private: GLTFImageIndex src_image = 0; + GLTFTextureSamplerIndex sampler = -1; protected: static void _bind_methods(); @@ -46,6 +47,8 @@ protected: public: GLTFImageIndex get_src_image() const; void set_src_image(GLTFImageIndex val); + GLTFTextureSamplerIndex get_sampler() const; + void set_sampler(GLTFTextureSamplerIndex val); }; #endif // GLTF_TEXTURE_H diff --git a/editor_modules/gltf/register_types.cpp b/editor_modules/gltf/register_types.cpp index 4ce376eaf..bd5e4b753 100644 --- a/editor_modules/gltf/register_types.cpp +++ b/editor_modules/gltf/register_types.cpp @@ -78,6 +78,7 @@ void register_gltf_types() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); diff --git a/modules/gltf/doc_classes/GLTFTextureSampler.xml b/modules/gltf/doc_classes/GLTFTextureSampler.xml new file mode 100644 index 000000000..9f468e671 --- /dev/null +++ b/modules/gltf/doc_classes/GLTFTextureSampler.xml @@ -0,0 +1,29 @@ + + + + Represents a GLTF texture sampler + + + Represents a texture sampler as defined by the base GLTF spec. Texture samplers in GLTF specify how to sample data from the texture's base image, when rendering the texture on an object. + + + + + + + + Texture's magnification filter, used when the texture appears larger on screen than the source image. + + + Texture's minification filter, used when the texture appears smaller on screen than the source image. + + + Wrapping mode to use for S-axis (horizontal) texture coordinates. + + + Wrapping mode to use for T-axis (vertical) texture coordinates. + + + + + diff --git a/modules/gltf/gltf_texture_sampler.cpp b/modules/gltf/gltf_texture_sampler.cpp new file mode 100644 index 000000000..6cf615b6c --- /dev/null +++ b/modules/gltf/gltf_texture_sampler.cpp @@ -0,0 +1,47 @@ +/*************************************************************************/ +/* gltf_texture_sampler.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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 "gltf_texture_sampler.h" + +void GLTFTextureSampler::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_mag_filter"), &GLTFTextureSampler::get_mag_filter); + ClassDB::bind_method(D_METHOD("set_mag_filter", "filter_mode"), &GLTFTextureSampler::set_mag_filter); + ClassDB::bind_method(D_METHOD("get_min_filter"), &GLTFTextureSampler::get_min_filter); + ClassDB::bind_method(D_METHOD("set_min_filter", "filter_mode"), &GLTFTextureSampler::set_min_filter); + ClassDB::bind_method(D_METHOD("get_wrap_s"), &GLTFTextureSampler::get_wrap_s); + ClassDB::bind_method(D_METHOD("set_wrap_s", "wrap_mode"), &GLTFTextureSampler::set_wrap_s); + ClassDB::bind_method(D_METHOD("get_wrap_t"), &GLTFTextureSampler::get_wrap_t); + ClassDB::bind_method(D_METHOD("set_wrap_t", "wrap_mode"), &GLTFTextureSampler::set_wrap_t); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "mag_filter"), "set_mag_filter", "get_mag_filter"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "min_filter"), "set_min_filter", "get_min_filter"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_s"), "set_wrap_s", "get_wrap_s"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_t"), "set_wrap_t", "get_wrap_t"); +} diff --git a/modules/gltf/gltf_texture_sampler.h b/modules/gltf/gltf_texture_sampler.h new file mode 100644 index 000000000..05f442845 --- /dev/null +++ b/modules/gltf/gltf_texture_sampler.h @@ -0,0 +1,165 @@ +/*************************************************************************/ +/* gltf_texture_sampler.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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 GLTF_TEXTURE_SAMPLER_H +#define GLTF_TEXTURE_SAMPLER_H + +#include "core/resource.h" +#include "scene/resources/texture.h" + +class GLTFTextureSampler : public Resource { + GDCLASS(GLTFTextureSampler, Resource); + +public: + enum FilterMode { + NEAREST = 9728, + LINEAR = 9729, + NEAREST_MIPMAP_NEAREST = 9984, + LINEAR_MIPMAP_NEAREST = 9985, + NEAREST_MIPMAP_LINEAR = 9986, + LINEAR_MIPMAP_LINEAR = 9987 + }; + + enum WrapMode { + CLAMP_TO_EDGE = 33071, + MIRRORED_REPEAT = 33648, + REPEAT = 10497 + }; + + int get_mag_filter() const { + return mag_filter; + } + + void set_mag_filter(const int filter_mode) { + mag_filter = (FilterMode)filter_mode; + } + + int get_min_filter() const { + return min_filter; + } + + void set_min_filter(const int filter_mode) { + min_filter = (FilterMode)filter_mode; + } + + int get_wrap_s() const { + return wrap_s; + } + + void set_wrap_s(const int wrap_mode) { + wrap_s = (WrapMode)wrap_mode; + } + + int get_wrap_t() const { + return wrap_t; + } + + void set_wrap_t(const int wrap_mode) { + wrap_s = (WrapMode)wrap_mode; + } + + Texture::Flags get_filter_mode() const { + switch (min_filter) { + case NEAREST: + return (Texture::Flags)0; + case LINEAR: + return Texture::Flags::FLAG_FILTER; + case NEAREST_MIPMAP_NEAREST: + case NEAREST_MIPMAP_LINEAR: + return Texture::Flags::FLAG_MIPMAPS; + case LINEAR_MIPMAP_NEAREST: + case LINEAR_MIPMAP_LINEAR: + default: + return (Texture::Flags)(Texture::Flags::FLAG_FILTER | Texture::Flags::FLAG_MIPMAPS); + } + } + + void set_filter_mode(uint32_t flags) { + const bool filter = (flags & Texture::Flags::FLAG_FILTER); + const bool mipmaps = (flags & Texture::Flags::FLAG_MIPMAPS); + + if (filter && mipmaps) { + min_filter = FilterMode::LINEAR_MIPMAP_LINEAR; + mag_filter = FilterMode::LINEAR; + } else if (filter) { + min_filter = FilterMode::LINEAR; + mag_filter = FilterMode::LINEAR; + } else if (mipmaps) { + min_filter = FilterMode::NEAREST_MIPMAP_LINEAR; + mag_filter = FilterMode::NEAREST; + } else { + min_filter = FilterMode::NEAREST; + mag_filter = FilterMode::NEAREST; + } + } + + Texture::Flags get_wrap_mode() const { + if ((wrap_s == WrapMode::MIRRORED_REPEAT) && (wrap_t == WrapMode::MIRRORED_REPEAT)) { + return Texture::Flags::FLAG_MIRRORED_REPEAT; + } else if ((wrap_s == WrapMode::REPEAT) && (wrap_t == WrapMode::REPEAT)) { + return Texture::Flags::FLAG_REPEAT; + } else { + return (Texture::Flags)0; + } + } + + void set_wrap_mode(uint32_t flags) { + if (flags & Texture::Flags::FLAG_MIRRORED_REPEAT) { + wrap_s = WrapMode::MIRRORED_REPEAT; + wrap_t = WrapMode::MIRRORED_REPEAT; + } else if (flags & Texture::Flags::FLAG_REPEAT) { + wrap_s = WrapMode::REPEAT; + wrap_t = WrapMode::REPEAT; + } else { + wrap_s = WrapMode::CLAMP_TO_EDGE; + wrap_t = WrapMode::CLAMP_TO_EDGE; + } + } + + Texture::Flags get_texture_flags() const { + return (Texture::Flags)(get_filter_mode() | get_wrap_mode()); + } + + void set_texture_flags(uint32_t flags) { + set_filter_mode(flags); + set_wrap_mode(flags); + } + +protected: + static void _bind_methods(); + +private: + FilterMode mag_filter = FilterMode::LINEAR; + FilterMode min_filter = FilterMode::LINEAR_MIPMAP_LINEAR; + WrapMode wrap_s = WrapMode::REPEAT; + WrapMode wrap_t = WrapMode::REPEAT; +}; + +#endif // GLTF_TEXTURE_SAMPLER_H