From 98aa804de525cec0f5be462b4d0056dea6f9ddf1 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 25 Aug 2014 22:37:36 +0200 Subject: [PATCH] Flipped texture coordinates Nazara now use a top-left corner origin for UVs (DirectX-like) Former-commit-id: 550dd76cf15bc731d1e23060d1af15c3cd5cb4fd --- examples/FirstScene/main.cpp | 4 +++ include/Nazara/Utility/Mesh.hpp | 3 ++ src/Nazara/Graphics/Loaders/OBJ/Loader.cpp | 2 +- src/Nazara/Renderer/Texture.cpp | 36 ++++++------------- src/Nazara/Utility/Loaders/MD2/Loader.cpp | 5 ++- src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp | 7 ++-- 6 files changed, 24 insertions(+), 33 deletions(-) diff --git a/examples/FirstScene/main.cpp b/examples/FirstScene/main.cpp index 65f948375..62a4425c8 100644 --- a/examples/FirstScene/main.cpp +++ b/examples/FirstScene/main.cpp @@ -95,6 +95,10 @@ int main() // Ce paramètre sert à indiquer la mise à l'échelle désirée lors du chargement du modèle. params.mesh.scale.Set(0.01f); // Un centième de la taille originelle + // Les UVs de ce fichier sont retournées (repère OpenGL, origine coin bas-gauche) par rapport à ce que le moteur attend + // Nous devons dire au moteur de les retourner lors du chargement + params.mesh.flipUVs = true; + // On charge ensuite le modèle depuis son fichier // Le moteur va charger le fichier et essayer de retrouver les fichiers associés (comme les matériaux, textures, ...) if (!spaceship.LoadFromFile("resources/Spaceship/spaceship.obj", params)) diff --git a/include/Nazara/Utility/Mesh.hpp b/include/Nazara/Utility/Mesh.hpp index 8c2036f05..116bbc3e7 100644 --- a/include/Nazara/Utility/Mesh.hpp +++ b/include/Nazara/Utility/Mesh.hpp @@ -36,6 +36,9 @@ struct NAZARA_API NzMeshParams // Faut-il centrer le mesh autour de l'origine ? bool center = false; + // Faut-il retourner les UV ? + bool flipUVs = false; + // Faut-il optimiser les index buffers ? (Rendu plus rapide, mais le chargement dure plus longtemps) bool optimizeIndexBuffers = true; diff --git a/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp b/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp index 449a82f2f..07c1742ec 100644 --- a/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp +++ b/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp @@ -142,7 +142,7 @@ namespace if (index >= 0) { const NzVector3f& uvw = texCoords[index]; - vertex.uv.Set(uvw.x, uvw.y); + vertex.uv.Set(uvw.x, (parameters.mesh.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé } else hasTexCoords = false; diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index 4a5996e4e..e19ef2bbf 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -1048,33 +1048,25 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s return false; } - nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_impl->format); - - unsigned int size = box.width*box.height*box.depth*bpp; - std::unique_ptr flipped(new nzUInt8[size]); - NzImage::Copy(flipped.get(), pixels, bpp, box.width, box.height, box.depth, 0, 0, srcWidth, srcHeight); - - // Inversion de la texture pour le repère d'OpenGL - if (!NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_impl->format, box.width, box.height, box.depth, flipped.get(), flipped.get())) - NazaraWarning("Failed to flip image"); - - SetUnpackAlignement(bpp); + SetUnpackAlignement(NzPixelFormat::GetBytesPerPixel(m_impl->format)); + glPixelStorei(GL_UNPACK_ROW_LENGTH, srcWidth); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, srcHeight); NzOpenGL::BindTexture(m_impl->type, m_impl->id); switch (m_impl->type) { case nzImageType_1D: - glTexSubImage1D(GL_TEXTURE_1D, level, box.x, box.width, format.dataFormat, format.dataType, flipped.get()); + glTexSubImage1D(GL_TEXTURE_1D, level, box.x, box.width, format.dataFormat, format.dataType, pixels); break; case nzImageType_1D_Array: case nzImageType_2D: - glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.width, box.height, format.dataFormat, format.dataType, flipped.get()); + glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.width, box.height, format.dataFormat, format.dataType, pixels); break; case nzImageType_2D_Array: case nzImageType_3D: - glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.z, box.width, box.height, box.depth, format.dataFormat, format.dataType, flipped.get()); + glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.z, box.width, box.height, box.depth, format.dataFormat, format.dataType, pixels); break; case nzImageType_Cubemap: @@ -1192,20 +1184,12 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe return false; } - nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_impl->format); - - // Inversion de la texture pour le repère d'OpenGL - unsigned int size = rect.width*rect.height*bpp; - std::unique_ptr flipped(new nzUInt8[size]); - NzImage::Copy(flipped.get(), pixels, bpp, rect.width, rect.height, 1, 0, 0, srcWidth, srcHeight); - - if (!NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_impl->format, rect.width, rect.height, 1, flipped.get(), flipped.get())) - NazaraWarning("Failed to flip image"); - - SetUnpackAlignement(bpp); + SetUnpackAlignement(NzPixelFormat::GetBytesPerPixel(m_impl->format)); + glPixelStorei(GL_UNPACK_ROW_LENGTH, srcWidth); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, srcHeight); NzOpenGL::BindTexture(m_impl->type, m_impl->id); - glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, flipped.get()); + glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, pixels); return true; } diff --git a/src/Nazara/Utility/Loaders/MD2/Loader.cpp b/src/Nazara/Utility/Loaders/MD2/Loader.cpp index 693711f75..f57c53340 100644 --- a/src/Nazara/Utility/Loaders/MD2/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD2/Loader.cpp @@ -200,7 +200,10 @@ namespace { const unsigned int fixedIndex = indexFix[j]; const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]]; - vertex[triangles[i].vertices[fixedIndex]].uv.Set(static_cast(texC.u) / header.skinwidth, 1.f - static_cast(texC.v)/header.skinheight); + float u = static_cast(texC.u) / header.skinwidth; + float v = static_cast(texC.v) / header.skinheight; + + vertex[triangles[i].vertices[fixedIndex]].uv.Set(u, (parameters.flipUVs) ? 1.f - v : v); } } diff --git a/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp b/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp index 8b0a88802..b2b518dae 100644 --- a/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp @@ -178,10 +178,7 @@ namespace } vertices->position = finalPos; - - // Le format MD5 spécifie ses UV avec l'origine en bas à gauche, contrairement au moteur - // dont l'origine est en haut à gauche, nous inversons donc la valeur en Y. - vertices->uv.Set(vertex.uv.x, 1.f - vertex.uv.y); + vertices->uv.Set(vertex.uv.x, (parameters.flipUVs) ? 1.f - vertex.uv.y : vertex.uv.y); // Inversion des UV si demandé vertices++; } @@ -271,7 +268,7 @@ namespace // On retourne le modèle dans le bon sens vertex->position = scale * (rotationQuat * finalPos); - vertex->uv.Set(md5Vertex.uv.x, 1.f - md5Vertex.uv.y); + vertex->uv.Set(md5Vertex.uv.x, (parameters.flipUVs) ? 1.f - md5Vertex.uv.y : md5Vertex.uv.y); // Inversion des UV si demandé vertex++; }