From 2a5560279b85cd79c5aa1b4d85588ff326ee5140 Mon Sep 17 00:00:00 2001 From: Razakhel Date: Sun, 24 Dec 2023 11:42:26 +0100 Subject: [PATCH] [Data/GltfLoad] Texcoords are normalized - They can be outside the [0; 1] range, and are wrapped according to the REPEAT mode --- src/RaZ/Data/GltfLoad.cpp | 21 ++++++++++++++++----- tests/src/RaZ/Data/GltfFormat.cpp | 8 ++++---- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/RaZ/Data/GltfLoad.cpp b/src/RaZ/Data/GltfLoad.cpp index 1ada0909..02ff52b2 100644 --- a/src/RaZ/Data/GltfLoad.cpp +++ b/src/RaZ/Data/GltfLoad.cpp @@ -60,12 +60,23 @@ void loadVertices(const fastgltf::Primitive& primitive, vert.position = Vec3f(data[0], data[1], data[2]); }); - // The tangent's input W component (data[3]) is either 1 or -1 and represents the handedness - // See: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#meshes-overview constexpr std::array, 3> attributes = {{ - { "TEXCOORD_0", [] (Vertex& vert, const float* data) { vert.texcoords = Vec2f(data[0], data[1]); } }, - { "NORMAL", [] (Vertex& vert, const float* data) { vert.normal = Vec3f(data[0], data[1], data[2]); } }, - { "TANGENT", [] (Vertex& vert, const float* data) { vert.tangent = Vec3f(data[0], data[1], data[2]) * data[3]; } } + { "TEXCOORD_0", [] (Vertex& vert, const float* data) { + // The texcoords can be outside the [0; 1] range; they're normalized according to the REPEAT mode. This may be subject to change + // See: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_wrapping + vert.texcoords = Vec2f(data[0], data[1]); + + for (float& elt : vert.texcoords.getData()) { + if (elt < -1.f || elt > 1.f) elt = std::fmod(elt, 1.f); + if (elt < 0.f) elt += 1.f; + } + }}, + { "NORMAL", [] (Vertex& vert, const float* data) { vert.normal = Vec3f(data[0], data[1], data[2]); } }, + { "TANGENT", [] (Vertex& vert, const float* data) { + // The tangent's input W component (data[3]) is either 1 or -1 and represents the handedness + // See: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#meshes-overview + vert.tangent = Vec3f(data[0], data[1], data[2]) * data[3]; + }} }}; for (auto&& [attribName, callback] : attributes) { diff --git a/tests/src/RaZ/Data/GltfFormat.cpp b/tests/src/RaZ/Data/GltfFormat.cpp index ee72e12b..8892b630 100644 --- a/tests/src/RaZ/Data/GltfFormat.cpp +++ b/tests/src/RaZ/Data/GltfFormat.cpp @@ -17,10 +17,10 @@ TEST_CASE("GltfFormat load glTF") { CHECK(mesh.getSubmeshes()[1].getTriangleIndexCount() == 36); CHECK(mesh.recoverTriangleCount() == 24); // 72 / 3 - CHECK(mesh.getSubmeshes()[0].getVertices()[0] == Raz::Vertex{ Raz::Vec3f(1.f, -1.f, 1.f), Raz::Vec2f(0.f, 0.f), -Raz::Axis::Y, -Raz::Axis::X }); - CHECK(mesh.getSubmeshes()[0].getVertices()[1] == Raz::Vertex{ Raz::Vec3f(-1.f, -1.f, -1.f), Raz::Vec2f(-1.f, 1.f), -Raz::Axis::Y, -Raz::Axis::X }); - CHECK(mesh.getSubmeshes()[0].getVertices()[17] == Raz::Vertex{ Raz::Vec3f(1.f, 1.f, -0.9999989f), Raz::Vec2f(0.f, 1.f), -Raz::Axis::Z, -Raz::Axis::X }); - CHECK(mesh.getSubmeshes()[0].getVertices()[35] == Raz::Vertex{ Raz::Vec3f(-1.f, 1.f, -1.f), Raz::Vec2f(-1.f, 1.f), -Raz::Axis::Z, -Raz::Axis::X }); + CHECK(mesh.getSubmeshes()[0].getVertices()[0] == Raz::Vertex{ Raz::Vec3f(1.f, -1.f, 1.f), Raz::Vec2f(0.f, 0.f), -Raz::Axis::Y, -Raz::Axis::X }); + CHECK(mesh.getSubmeshes()[0].getVertices()[1] == Raz::Vertex{ Raz::Vec3f(-1.f, -1.f, -1.f), Raz::Vec2f(0.f, 1.f), -Raz::Axis::Y, -Raz::Axis::X }); + CHECK(mesh.getSubmeshes()[0].getVertices()[17] == Raz::Vertex{ Raz::Vec3f(1.f, 1.f, -0.9999989f), Raz::Vec2f(0.f, 1.f), -Raz::Axis::Z, -Raz::Axis::X }); + CHECK(mesh.getSubmeshes()[0].getVertices()[35] == Raz::Vertex{ Raz::Vec3f(-1.f, 1.f, -1.f), Raz::Vec2f(0.f, 1.f), -Raz::Axis::Z, -Raz::Axis::X }); REQUIRE(meshRenderer.getSubmeshRenderers().size() == 2); CHECK(meshRenderer.getSubmeshRenderers()[0].getRenderMode() == Raz::RenderMode::TRIANGLE);