GLTF imports & exports material texture filters

This commit is contained in:
The Tophat Demon 2021-10-04 10:49:42 -05:00 committed by Relintai
parent 25d8fbdba4
commit 3b7eb818e3
13 changed files with 454 additions and 29 deletions

View File

@ -22,6 +22,7 @@ def get_doc_classes():
"GLTFSpecGloss", "GLTFSpecGloss",
"GLTFState", "GLTFState",
"GLTFTexture", "GLTFTexture",
"GLTFTextureSampler",
"PackedSceneGLTF", "PackedSceneGLTF",
] ]

View File

@ -86,6 +86,12 @@
<description> <description>
</description> </description>
</method> </method>
<method name="get_texture_samplers">
<return type="Array" />
<description>
Retrieves the array of texture samplers that are used by the textures contained in the GLTF.
</description>
</method>
<method name="get_textures"> <method name="get_textures">
<return type="Array" /> <return type="Array" />
<description> <description>
@ -173,6 +179,13 @@
<description> <description>
</description> </description>
</method> </method>
<method name="set_texture_samplers">
<return type="void" />
<argument index="0" name="texture_samplers" type="Array" />
<description>
Sets the array of texture samplers that are used by the textures contained in the GLTF.
</description>
</method>
<method name="set_textures"> <method name="set_textures">
<return type="void" /> <return type="void" />
<argument index="0" name="textures" type="Array" /> <argument index="0" name="textures" type="Array" />

View File

@ -10,6 +10,9 @@
<methods> <methods>
</methods> </methods>
<members> <members>
<member name="sampler" type="int" setter="set_sampler" getter="get_sampler" default="-1">
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).
</member>
<member name="src_image" type="int" setter="set_src_image" getter="get_src_image" default="0"> <member name="src_image" type="int" setter="set_src_image" getter="get_src_image" default="0">
</member> </member>
</members> </members>

View File

@ -135,71 +135,71 @@ Error GLTFDocument::serialize(Ref<GLTFState> state, Node *p_root, const String &
return Error::FAILED; 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); err = _serialize_animations(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 8 SERIALIZE ACCESSORS */ /* STEP 9 SERIALIZE ACCESSORS */
err = _encode_accessors(state); err = _encode_accessors(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 9 SERIALIZE IMAGES */ /* STEP 10 SERIALIZE IMAGES */
err = _serialize_images(state, p_path); err = _serialize_images(state, p_path);
if (err != OK) { if (err != OK) {
return Error::FAILED; 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++) { for (GLTFBufferViewIndex i = 0; i < state->buffer_views.size(); i++) {
state->buffer_views.write[i]->buffer = 0; state->buffer_views.write[i]->buffer = 0;
} }
/* STEP 11 SERIALIZE BUFFER VIEWS */ /* STEP 12 SERIALIZE BUFFER VIEWS */
err = _encode_buffer_views(state); err = _encode_buffer_views(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 12 SERIALIZE NODES */ /* STEP 13 SERIALIZE NODES */
err = _serialize_nodes(state); err = _serialize_nodes(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 13 SERIALIZE SCENE */ /* STEP 15 SERIALIZE SCENE */
err = _serialize_scenes(state); err = _serialize_scenes(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 14 SERIALIZE SCENE */ /* STEP 16 SERIALIZE SCENE */
err = _serialize_lights(state); err = _serialize_lights(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 15 SERIALIZE EXTENSIONS */ /* STEP 17 SERIALIZE EXTENSIONS */
err = _serialize_extensions(state); err = _serialize_extensions(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 16 SERIALIZE VERSION */ /* STEP 18 SERIALIZE VERSION */
err = _serialize_version(state); err = _serialize_version(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 17 SERIALIZE FILE */ /* STEP 19 SERIALIZE FILE */
err = _serialize_file(state, p_path); err = _serialize_file(state, p_path);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
@ -2950,7 +2950,7 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path
ERR_CONTINUE(state->images[i].is_null()); ERR_CONTINUE(state->images[i].is_null());
Ref<Image> image = state->images[i]->get_data(); Ref<Image> image = state->images[i];
ERR_CONTINUE(image.is_null()); ERR_CONTINUE(image.is_null());
if (p_path.to_lower().ends_with("glb")) { if (p_path.to_lower().ends_with("glb")) {
@ -3155,11 +3155,7 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat
continue; continue;
} }
Ref<ImageTexture> t; state->images.push_back(img);
t.instance();
t->create_from_image(img);
state->images.push_back(t);
} }
print_verbose("glTF: Total images: " + itos(state->images.size())); print_verbose("glTF: Total images: " + itos(state->images.size()));
@ -3178,6 +3174,11 @@ Error GLTFDocument::_serialize_textures(Ref<GLTFState> state) {
Ref<GLTFTexture> t = state->textures[i]; Ref<GLTFTexture> t = state->textures[i];
ERR_CONTINUE(t->get_src_image() == -1); ERR_CONTINUE(t->get_src_image() == -1);
d["source"] = t->get_src_image(); d["source"] = t->get_src_image();
GLTFTextureSamplerIndex sampler_index = t->get_sampler();
if (sampler_index != -1) {
d["sampler"] = sampler_index;
}
textures.push_back(d); textures.push_back(d);
} }
state->json["textures"] = textures; state->json["textures"] = textures;
@ -3199,7 +3200,24 @@ Error GLTFDocument::_parse_textures(Ref<GLTFState> state) {
Ref<GLTFTexture> t; Ref<GLTFTexture> t;
t.instance(); t.instance();
t->set_src_image(d["source"]); 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); state->textures.push_back(t);
// Create and cache the texture used in the engine
Ref<ImageTexture> imgTex;
imgTex.instance();
imgTex->create_from_image(state->images[t->get_src_image()]);
// Set texture filter and repeat based on sampler settings
const Ref<GLTFTextureSampler> 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; return OK;
@ -3207,24 +3225,124 @@ Error GLTFDocument::_parse_textures(Ref<GLTFState> state) {
GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture> p_texture) { GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture> p_texture) {
ERR_FAIL_COND_V(p_texture.is_null(), -1); 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<GLTFTexture> gltf_texture; Ref<GLTFTexture> gltf_texture;
gltf_texture.instance(); gltf_texture.instance();
ERR_FAIL_COND_V(p_texture->get_data().is_null(), -1);
GLTFImageIndex gltf_src_image_i = state->images.size(); 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_src_image(gltf_src_image_i);
gltf_texture->set_sampler(gltf_sampler_i);
GLTFTextureIndex gltf_texture_i = state->textures.size(); GLTFTextureIndex gltf_texture_i = state->textures.size();
state->textures.push_back(gltf_texture); state->textures.push_back(gltf_texture);
state->texture_cache[gltf_texture_i] = p_texture;
return gltf_texture_i; return gltf_texture_i;
} }
Ref<Texture> GLTFDocument::_get_texture(Ref<GLTFState> state, const GLTFTextureIndex p_texture) { Ref<Texture> GLTFDocument::_get_texture(Ref<GLTFState> state, const GLTFTextureIndex p_texture) {
ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref<Texture>()); ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref<Texture>());
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<Texture>()); GLTFTextureSamplerIndex GLTFDocument::_set_sampler_for_mode(Ref<GLTFState> 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<GLTFTextureSampler> gltf_sampler;
gltf_sampler.instance();
gltf_sampler->set_texture_flags(p_mode);
state->texture_samplers.push_back(gltf_sampler);
return gltf_sampler_i;
}
Ref<GLTFTextureSampler> GLTFDocument::_get_sampler_for_texture(Ref<GLTFState> state, const GLTFTextureIndex p_texture) {
ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref<Texture>());
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<GLTFTextureSampler>());
return state->texture_samplers[sampler];
}
}
Error GLTFDocument::_serialize_texture_samplers(Ref<GLTFState> state) {
if (!state->texture_samplers.size()) {
return OK;
}
Array samplers;
for (int32_t i = 0; i < state->texture_samplers.size(); ++i) {
Dictionary d;
Ref<GLTFTextureSampler> 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<GLTFState> 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<GLTFTextureSampler> 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<GLTFState> state) { Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
@ -6668,13 +6786,19 @@ Error GLTFDocument::parse(Ref<GLTFState> state, String p_path, bool p_read_binar
return Error::FAILED; return Error::FAILED;
} }
/* PARSE TEXTURE SAMPLERS */
err = _parse_texture_samplers(state);
if (err != OK) {
return Error::FAILED;
}
/* PARSE TEXTURES */ /* PARSE TEXTURES */
err = _parse_textures(state); err = _parse_textures(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* PARSE TEXTURES */ /* PARSE MATERIALS */
err = _parse_materials(state); err = _parse_materials(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;

View File

@ -52,6 +52,7 @@ class GLTFSkin;
class GLTFNode; class GLTFNode;
class GLTFSpecGloss; class GLTFSpecGloss;
class GLTFSkeleton; class GLTFSkeleton;
class GLTFTextureSampler;
class MultiMeshInstance; class MultiMeshInstance;
using GLTFAccessorIndex = int; using GLTFAccessorIndex = int;
@ -67,6 +68,7 @@ using GLTFNodeIndex = int;
using GLTFSkeletonIndex = int; using GLTFSkeletonIndex = int;
using GLTFSkinIndex = int; using GLTFSkinIndex = int;
using GLTFTextureIndex = int; using GLTFTextureIndex = int;
using GLTFTextureSamplerIndex = int;
class GLTFDocument : public Resource { class GLTFDocument : public Resource {
GDCLASS(GLTFDocument, Resource); GDCLASS(GLTFDocument, Resource);
@ -178,6 +180,10 @@ private:
GLTFTextureIndex _set_texture(Ref<GLTFState> state, Ref<Texture> p_texture); GLTFTextureIndex _set_texture(Ref<GLTFState> state, Ref<Texture> p_texture);
Ref<Texture> _get_texture(Ref<GLTFState> state, Ref<Texture> _get_texture(Ref<GLTFState> state,
const GLTFTextureIndex p_texture); const GLTFTextureIndex p_texture);
GLTFTextureSamplerIndex _set_sampler_for_mode(Ref<GLTFState> state,
uint32_t p_mode);
Ref<GLTFTextureSampler> _get_sampler_for_texture(Ref<GLTFState> state,
const GLTFTextureIndex p_texture);
Error _parse_json(const String &p_path, Ref<GLTFState> state); Error _parse_json(const String &p_path, Ref<GLTFState> state);
Error _parse_glb(const String &p_path, Ref<GLTFState> state); Error _parse_glb(const String &p_path, Ref<GLTFState> state);
void _compute_node_heights(Ref<GLTFState> state); void _compute_node_heights(Ref<GLTFState> state);
@ -225,10 +231,12 @@ private:
const bool p_for_vertex); const bool p_for_vertex);
Error _parse_meshes(Ref<GLTFState> state); Error _parse_meshes(Ref<GLTFState> state);
Error _serialize_textures(Ref<GLTFState> state); Error _serialize_textures(Ref<GLTFState> state);
Error _serialize_texture_samplers(Ref<GLTFState> state);
Error _serialize_images(Ref<GLTFState> state, const String &p_path); Error _serialize_images(Ref<GLTFState> state, const String &p_path);
Error _serialize_lights(Ref<GLTFState> state); Error _serialize_lights(Ref<GLTFState> state);
Error _parse_images(Ref<GLTFState> state, const String &p_base_path); Error _parse_images(Ref<GLTFState> state, const String &p_base_path);
Error _parse_textures(Ref<GLTFState> state); Error _parse_textures(Ref<GLTFState> state);
Error _parse_texture_samplers(Ref<GLTFState> state);
Error _parse_materials(Ref<GLTFState> state); Error _parse_materials(Ref<GLTFState> state);
void _set_texture_transform_uv1(const Dictionary &d, Ref<SpatialMaterial> material); void _set_texture_transform_uv1(const Dictionary &d, Ref<SpatialMaterial> material);
void spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, void spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss,

View File

@ -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("set_root_nodes", "root_nodes"), &GLTFState::set_root_nodes);
ClassDB::bind_method(D_METHOD("get_textures"), &GLTFState::get_textures); 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("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("get_images"), &GLTFState::get_images);
ClassDB::bind_method(D_METHOD("set_images", "images"), &GLTFState::set_images); ClassDB::bind_method(D_METHOD("set_images", "images"), &GLTFState::set_images);
ClassDB::bind_method(D_METHOD("get_skins"), &GLTFState::get_skins); 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::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<int> ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "root_nodes"), "set_root_nodes", "get_root_nodes"); // Vector<int>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_textures", "get_textures"); // Vector<Ref<GLTFTexture>> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_textures", "get_textures"); // Vector<Ref<GLTFTexture>>
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<Ref<GLTFTextureSampler>>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "images", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_images", "get_images"); // Vector<Ref<Texture> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "images", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_images", "get_images"); // Vector<Ref<Texture>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skins", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skins", "get_skins"); // Vector<Ref<GLTFSkin>> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skins", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skins", "get_skins"); // Vector<Ref<GLTFSkin>>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "cameras", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_cameras", "get_cameras"); // Vector<Ref<GLTFCamera>> ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "cameras", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_cameras", "get_cameras"); // Vector<Ref<GLTFCamera>>
@ -218,6 +221,14 @@ void GLTFState::set_textures(Array p_textures) {
GLTFDocument::set_from_array(textures, 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() { Array GLTFState::get_images() {
return GLTFDocument::to_array(images); return GLTFDocument::to_array(images);
} }

View File

@ -47,6 +47,9 @@
#include "gltf_skeleton.h" #include "gltf_skeleton.h"
#include "gltf_skin.h" #include "gltf_skin.h"
#include "gltf_texture.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 { class GLTFState : public Resource {
GDCLASS(GLTFState, Resource); GDCLASS(GLTFState, Resource);
@ -77,7 +80,10 @@ class GLTFState : public Resource {
String scene_name; String scene_name;
Vector<int> root_nodes; Vector<int> root_nodes;
Vector<Ref<GLTFTexture>> textures; Vector<Ref<GLTFTexture>> textures;
Vector<Ref<Texture>> images; Vector<Ref<GLTFTextureSampler>> texture_samplers;
Ref<GLTFTextureSampler> default_texture_sampler;
Vector<Ref<Image>> images;
Map<GLTFTextureIndex, Ref<Texture>> texture_cache;
Vector<Ref<GLTFSkin>> skins; Vector<Ref<GLTFSkin>> skins;
Vector<Ref<GLTFCamera>> cameras; Vector<Ref<GLTFCamera>> cameras;
@ -139,6 +145,9 @@ public:
Array get_textures(); Array get_textures();
void set_textures(Array p_textures); void set_textures(Array p_textures);
Array get_texture_samplers();
void set_texture_samplers(Array p_texture_samplers);
Array get_images(); Array get_images();
void set_images(Array p_images); void set_images(Array p_images);

View File

@ -33,8 +33,11 @@
void GLTFTexture::_bind_methods() { void GLTFTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_src_image"), &GLTFTexture::get_src_image); 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("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, "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 { GLTFImageIndex GLTFTexture::get_src_image() const {
@ -44,3 +47,11 @@ GLTFImageIndex GLTFTexture::get_src_image() const {
void GLTFTexture::set_src_image(GLTFImageIndex val) { void GLTFTexture::set_src_image(GLTFImageIndex val) {
src_image = val; src_image = val;
} }
GLTFTextureSamplerIndex GLTFTexture::get_sampler() const {
return sampler;
}
void GLTFTexture::set_sampler(GLTFTextureSamplerIndex val) {
sampler = val;
}

View File

@ -39,6 +39,7 @@ class GLTFTexture : public Resource {
private: private:
GLTFImageIndex src_image = 0; GLTFImageIndex src_image = 0;
GLTFTextureSamplerIndex sampler = -1;
protected: protected:
static void _bind_methods(); static void _bind_methods();
@ -46,6 +47,8 @@ protected:
public: public:
GLTFImageIndex get_src_image() const; GLTFImageIndex get_src_image() const;
void set_src_image(GLTFImageIndex val); void set_src_image(GLTFImageIndex val);
GLTFTextureSamplerIndex get_sampler() const;
void set_sampler(GLTFTextureSamplerIndex val);
}; };
#endif // GLTF_TEXTURE_H #endif // GLTF_TEXTURE_H

View File

@ -78,6 +78,7 @@ void register_gltf_types() {
ClassDB::register_class<GLTFBufferView>(); ClassDB::register_class<GLTFBufferView>();
ClassDB::register_class<GLTFAccessor>(); ClassDB::register_class<GLTFAccessor>();
ClassDB::register_class<GLTFTexture>(); ClassDB::register_class<GLTFTexture>();
ClassDB::register_class<GLTFTextureSampler>();
ClassDB::register_class<GLTFSkeleton>(); ClassDB::register_class<GLTFSkeleton>();
ClassDB::register_class<GLTFSkin>(); ClassDB::register_class<GLTFSkin>();
ClassDB::register_class<GLTFCamera>(); ClassDB::register_class<GLTFCamera>();

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="GLTFTextureSampler" inherits="Resource" version="3.6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
Represents a GLTF texture sampler
</brief_description>
<description>
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.
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<members>
<member name="mag_filter" type="int" setter="set_mag_filter" getter="get_mag_filter" default="9729">
Texture's magnification filter, used when the texture appears larger on screen than the source image.
</member>
<member name="min_filter" type="int" setter="set_min_filter" getter="get_min_filter" default="9987">
Texture's minification filter, used when the texture appears smaller on screen than the source image.
</member>
<member name="wrap_s" type="int" setter="set_wrap_s" getter="get_wrap_s" default="10497">
Wrapping mode to use for S-axis (horizontal) texture coordinates.
</member>
<member name="wrap_t" type="int" setter="set_wrap_t" getter="get_wrap_t" default="10497">
Wrapping mode to use for T-axis (vertical) texture coordinates.
</member>
</members>
<constants>
</constants>
</class>

View File

@ -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");
}

View File

@ -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