diff --git a/irr/include/vector2d.h b/irr/include/vector2d.h index 4c41389f4..caf69e6be 100644 --- a/irr/include/vector2d.h +++ b/irr/include/vector2d.h @@ -8,6 +8,7 @@ #include "dimension2d.h" #include +#include namespace irr { @@ -34,6 +35,9 @@ public: constexpr vector2d(const dimension2d &other) : X(other.Width), Y(other.Height) {} + explicit constexpr vector2d(const std::array &arr) : + X(arr[0]), Y(arr[1]) {} + // operators vector2d operator-() const { return vector2d(-X, -Y); } diff --git a/irr/src/CGLTFMeshFileLoader.cpp b/irr/src/CGLTFMeshFileLoader.cpp index 8ac96d4f4..ab04fae8e 100644 --- a/irr/src/CGLTFMeshFileLoader.cpp +++ b/irr/src/CGLTFMeshFileLoader.cpp @@ -3,6 +3,7 @@ #include "CGLTFMeshFileLoader.h" +#include "SMaterialLayer.h" #include "coreutil.h" #include "CSkinnedMesh.h" #include "ISkinnedMesh.h" @@ -11,6 +12,7 @@ #include "matrix4.h" #include "path.h" #include "quaternion.h" +#include "vector2d.h" #include "vector3d.h" #include "os.h" @@ -381,6 +383,20 @@ static std::vector generateIndices(const std::size_t nVerts) return indices; } +using Wrap = tiniergltf::Sampler::Wrap; +static video::E_TEXTURE_CLAMP convertTextureWrap(const Wrap wrap) { + switch (wrap) { + case Wrap::REPEAT: + return video::ETC_REPEAT; + case Wrap::CLAMP_TO_EDGE: + return video::ETC_CLAMP_TO_EDGE; + case Wrap::MIRRORED_REPEAT: + return video::ETC_MIRROR; + default: + throw std::runtime_error("invalid sampler wrapping mode"); + } +} + /** * Load up the rawest form of the model. The vertex positions and indices. * Documentation: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#meshes @@ -415,6 +431,8 @@ void SelfType::MeshExtractor::loadMesh( m_irr_model->addMeshBuffer( new SSkinMeshBuffer(std::move(*vertices), std::move(indices))); + auto *meshbuf = m_irr_model->getMeshBuffer(m_irr_model->getMeshBufferCount() - 1); + auto &irr_mat = meshbuf->getMaterial(); if (primitive.material.has_value()) { const auto &material = m_gltf_model.materials->at(*primitive.material); @@ -423,6 +441,13 @@ void SelfType::MeshExtractor::loadMesh( if (texture.has_value()) { const auto meshbufNr = m_irr_model->getMeshBufferCount() - 1; m_irr_model->setTextureSlot(meshbufNr, static_cast(texture->index)); + const auto samplerIdx = m_gltf_model.textures->at(texture->index).sampler; + if (samplerIdx.has_value()) { + auto &sampler = m_gltf_model.samplers->at(*samplerIdx); + auto &layer = irr_mat.TextureLayers[0]; + layer.TextureWrapU = convertTextureWrap(sampler.wrapS); + layer.TextureWrapV = convertTextureWrap(sampler.wrapT); + } } } } @@ -650,11 +675,19 @@ void SelfType::MeshExtractor::copyTCoords( const std::size_t accessorIdx, std::vector& vertices) const { - const auto accessor = createNormalizedValuesAccessor<2>(m_gltf_model, accessorIdx); - const auto count = std::visit([](auto &&a) { return a.getCount(); }, accessor); - for (std::size_t i = 0; i < count; ++i) { - const auto vals = getNormalizedValues(accessor, i); - vertices[i].TCoords = core::vector2df(vals[0], vals[1]); + const auto componentType = m_gltf_model.accessors->at(accessorIdx).componentType; + if (componentType == tiniergltf::Accessor::ComponentType::FLOAT) { + // If floats are used, they need not be normalized: Wrapping may take effect. + const auto accessor = Accessor>::make(m_gltf_model, accessorIdx); + for (std::size_t i = 0; i < accessor.getCount(); ++i) { + vertices[i].TCoords = core::vector2d(accessor.get(i)); + } + } else { + const auto accessor = createNormalizedValuesAccessor<2>(m_gltf_model, accessorIdx); + const auto count = std::visit([](auto &&a) { return a.getCount(); }, accessor); + for (std::size_t i = 0; i < count; ++i) { + vertices[i].TCoords = core::vector2d(getNormalizedValues(accessor, i)); + } } } diff --git a/lib/tiniergltf/tiniergltf.hpp b/lib/tiniergltf/tiniergltf.hpp index d4db7cc64..35440f5dd 100644 --- a/lib/tiniergltf/tiniergltf.hpp +++ b/lib/tiniergltf/tiniergltf.hpp @@ -980,21 +980,16 @@ struct Sampler { }; std::optional minFilter; std::optional name; - enum class WrapS { + enum class Wrap { REPEAT, CLAMP_TO_EDGE, MIRRORED_REPEAT, }; - WrapS wrapS; - enum class WrapT { - REPEAT, - CLAMP_TO_EDGE, - MIRRORED_REPEAT, - }; - WrapT wrapT; + Wrap wrapS; + Wrap wrapT; Sampler(const Json::Value &o) - : wrapS(WrapS::REPEAT) - , wrapT(WrapT::REPEAT) + : wrapS(Wrap::REPEAT) + , wrapT(Wrap::REPEAT) { check(o.isObject()); if (o.isMember("magFilter")) { @@ -1020,21 +1015,16 @@ struct Sampler { if (o.isMember("name")) { name = as(o["name"]); } + static std::unordered_map map = { + {10497, Wrap::REPEAT}, + {33071, Wrap::CLAMP_TO_EDGE}, + {33648, Wrap::MIRRORED_REPEAT}, + }; if (o.isMember("wrapS")) { - static std::unordered_map map = { - {10497, WrapS::REPEAT}, - {33071, WrapS::CLAMP_TO_EDGE}, - {33648, WrapS::MIRRORED_REPEAT}, - }; const auto &v = o["wrapS"]; check(v.isUInt64()); wrapS = map.at(v.asUInt64()); } if (o.isMember("wrapT")) { - static std::unordered_map map = { - {10497, WrapT::REPEAT}, - {33071, WrapT::CLAMP_TO_EDGE}, - {33648, WrapT::MIRRORED_REPEAT}, - }; const auto &v = o["wrapT"]; check(v.isUInt64()); wrapT = map.at(v.asUInt64()); }