From 8c35461af2e8e6649fedce2e92864669039808f6 Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Wed, 22 May 2024 15:58:10 +0200 Subject: [PATCH] Fix/improve reading from accessors - Alignment issues - Use os::Byteswap::byteswap - Directly write into matrices --- irr/src/CGLTFMeshFileLoader.cpp | 79 +++++++++++++-------------------- irr/src/CGLTFMeshFileLoader.h | 2 +- 2 files changed, 31 insertions(+), 50 deletions(-) diff --git a/irr/src/CGLTFMeshFileLoader.cpp b/irr/src/CGLTFMeshFileLoader.cpp index 577a9d23d..6e7cd3ee6 100644 --- a/irr/src/CGLTFMeshFileLoader.cpp +++ b/irr/src/CGLTFMeshFileLoader.cpp @@ -12,6 +12,7 @@ #include "path.h" #include "quaternion.h" #include "vector3d.h" +#include "os.h" #include "tiniergltf.hpp" @@ -163,24 +164,23 @@ SelfType::Accessor::make(const tiniergltf::GlTF &model, std::size_t accessorI return tiniergltf::Accessor::ComponentType::V; \ } -#define VEC_ACCESSOR_TYPES(T, U, n) \ +#define VEC_ACCESSOR_TYPES(T, U, N) \ template <> \ - constexpr tiniergltf::Accessor::Type SelfType::Accessor>::getType() \ + constexpr tiniergltf::Accessor::Type SelfType::Accessor>::getType() \ { \ - return tiniergltf::Accessor::Type::VEC##n; \ + return tiniergltf::Accessor::Type::VEC##N; \ } \ template <> \ - constexpr tiniergltf::Accessor::ComponentType SelfType::Accessor>::getComponentType() \ + constexpr tiniergltf::Accessor::ComponentType SelfType::Accessor>::getComponentType() \ { \ return tiniergltf::Accessor::ComponentType::U; \ } \ template <> \ - std::array SelfType::rawget(const void *ptr) \ + std::array SelfType::rawget(const u8 *ptr) \ { \ - const T *tptr = reinterpret_cast(ptr); \ - std::array res; \ - for (u8 i = 0; i < n; ++i) \ - res[i] = rawget(tptr + i); \ + std::array res; \ + for (u8 i = 0; i < N; ++i) \ + res[i] = rawget(ptr + sizeof(T) * i); \ return res; \ } @@ -217,66 +217,47 @@ T SelfType::Accessor::get(std::size_t i) const return T(); } -// Note: clang and gcc should both optimize this out. -static inline bool is_big_endian() -{ -#ifdef __BIG_ENDIAN__ - return true; -#else - return false; -#endif -} - template -T SelfType::rawget(const void *ptr) +T SelfType::rawget(const u8 *ptr) { - if (!is_big_endian()) - return *reinterpret_cast(ptr); - // glTF uses little endian. - // On big-endian systems, we have to swap the byte order. - // TODO test this on a big endian system - const u8 *bptr = reinterpret_cast(ptr); - u8 bytes[sizeof(T)]; - for (std::size_t i = 0; i < sizeof(T); ++i) { - bytes[sizeof(T) - i - 1] = bptr[i]; - } - return *reinterpret_cast(bytes); + T dest; + std::memcpy(&dest, ptr, sizeof(dest)); +#ifdef __BIG_ENDIAN__ + return os::Byteswap::byteswap(dest); +#else + return dest; +#endif } // Note that these "more specialized templates" should win. template <> -core::matrix4 SelfType::rawget(const void *ptr) +core::matrix4 SelfType::rawget(const u8 *ptr) { - const f32 *fptr = reinterpret_cast(ptr); - f32 M[16]; - for (u8 i = 0; i < 16; ++i) { - M[i] = rawget(fptr + i); - } core::matrix4 mat; - mat.setM(M); + for (u8 i = 0; i < 16; ++i) { + mat[i] = rawget(ptr + i * sizeof(f32)); + } return mat; } template <> -core::vector3df SelfType::rawget(const void *ptr) +core::vector3df SelfType::rawget(const u8 *ptr) { - const f32 *fptr = reinterpret_cast(ptr); return core::vector3df( - rawget(fptr), - rawget(fptr + 1), - rawget(fptr + 2)); + rawget(ptr), + rawget(ptr + sizeof(f32)), + rawget(ptr + 2 * sizeof(f32))); } template <> -core::quaternion SelfType::rawget(const void *ptr) +core::quaternion SelfType::rawget(const u8 *ptr) { - const f32 *fptr = reinterpret_cast(ptr); return core::quaternion( - rawget(fptr), - rawget(fptr + 1), - rawget(fptr + 2), - rawget(fptr + 3)); + rawget(ptr), + rawget(ptr + sizeof(f32)), + rawget(ptr + 2 * sizeof(f32)), + rawget(ptr + 3 * sizeof(f32))); } template diff --git a/irr/src/CGLTFMeshFileLoader.h b/irr/src/CGLTFMeshFileLoader.h index 16f442326..d17305d25 100644 --- a/irr/src/CGLTFMeshFileLoader.h +++ b/irr/src/CGLTFMeshFileLoader.h @@ -32,7 +32,7 @@ class CGLTFMeshFileLoader : public IMeshLoader private: template - static T rawget(const void *ptr); + static T rawget(const u8 *ptr); template class Accessor