Fix/improve reading from accessors

- Alignment issues
- Use os::Byteswap::byteswap
- Directly write into matrices
This commit is contained in:
Lars Mueller 2024-05-22 15:58:10 +02:00
parent be375cdfb6
commit 8c35461af2
2 changed files with 31 additions and 50 deletions

@ -12,6 +12,7 @@
#include "path.h" #include "path.h"
#include "quaternion.h" #include "quaternion.h"
#include "vector3d.h" #include "vector3d.h"
#include "os.h"
#include "tiniergltf.hpp" #include "tiniergltf.hpp"
@ -163,24 +164,23 @@ SelfType::Accessor<T>::make(const tiniergltf::GlTF &model, std::size_t accessorI
return tiniergltf::Accessor::ComponentType::V; \ return tiniergltf::Accessor::ComponentType::V; \
} }
#define VEC_ACCESSOR_TYPES(T, U, n) \ #define VEC_ACCESSOR_TYPES(T, U, N) \
template <> \ template <> \
constexpr tiniergltf::Accessor::Type SelfType::Accessor<std::array<T, n>>::getType() \ constexpr tiniergltf::Accessor::Type SelfType::Accessor<std::array<T, N>>::getType() \
{ \ { \
return tiniergltf::Accessor::Type::VEC##n; \ return tiniergltf::Accessor::Type::VEC##N; \
} \ } \
template <> \ template <> \
constexpr tiniergltf::Accessor::ComponentType SelfType::Accessor<std::array<T, n>>::getComponentType() \ constexpr tiniergltf::Accessor::ComponentType SelfType::Accessor<std::array<T, N>>::getComponentType() \
{ \ { \
return tiniergltf::Accessor::ComponentType::U; \ return tiniergltf::Accessor::ComponentType::U; \
} \ } \
template <> \ template <> \
std::array<T, n> SelfType::rawget(const void *ptr) \ std::array<T, N> SelfType::rawget(const u8 *ptr) \
{ \ { \
const T *tptr = reinterpret_cast<const T *>(ptr); \ std::array<T, N> res; \
std::array<T, n> res; \ for (u8 i = 0; i < N; ++i) \
for (u8 i = 0; i < n; ++i) \ res[i] = rawget<T>(ptr + sizeof(T) * i); \
res[i] = rawget<T>(tptr + i); \
return res; \ return res; \
} }
@ -217,66 +217,47 @@ T SelfType::Accessor<T>::get(std::size_t i) const
return T(); 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 <typename T> template <typename T>
T SelfType::rawget(const void *ptr) T SelfType::rawget(const u8 *ptr)
{ {
if (!is_big_endian()) T dest;
return *reinterpret_cast<const T *>(ptr); std::memcpy(&dest, ptr, sizeof(dest));
// glTF uses little endian. #ifdef __BIG_ENDIAN__
// On big-endian systems, we have to swap the byte order. return os::Byteswap::byteswap(dest);
// TODO test this on a big endian system #else
const u8 *bptr = reinterpret_cast<const u8 *>(ptr); return dest;
u8 bytes[sizeof(T)]; #endif
for (std::size_t i = 0; i < sizeof(T); ++i) {
bytes[sizeof(T) - i - 1] = bptr[i];
}
return *reinterpret_cast<const T *>(bytes);
} }
// Note that these "more specialized templates" should win. // Note that these "more specialized templates" should win.
template <> template <>
core::matrix4 SelfType::rawget(const void *ptr) core::matrix4 SelfType::rawget(const u8 *ptr)
{ {
const f32 *fptr = reinterpret_cast<const f32 *>(ptr);
f32 M[16];
for (u8 i = 0; i < 16; ++i) {
M[i] = rawget<f32>(fptr + i);
}
core::matrix4 mat; core::matrix4 mat;
mat.setM(M); for (u8 i = 0; i < 16; ++i) {
mat[i] = rawget<f32>(ptr + i * sizeof(f32));
}
return mat; return mat;
} }
template <> template <>
core::vector3df SelfType::rawget(const void *ptr) core::vector3df SelfType::rawget(const u8 *ptr)
{ {
const f32 *fptr = reinterpret_cast<const f32 *>(ptr);
return core::vector3df( return core::vector3df(
rawget<f32>(fptr), rawget<f32>(ptr),
rawget<f32>(fptr + 1), rawget<f32>(ptr + sizeof(f32)),
rawget<f32>(fptr + 2)); rawget<f32>(ptr + 2 * sizeof(f32)));
} }
template <> template <>
core::quaternion SelfType::rawget(const void *ptr) core::quaternion SelfType::rawget(const u8 *ptr)
{ {
const f32 *fptr = reinterpret_cast<const f32 *>(ptr);
return core::quaternion( return core::quaternion(
rawget<f32>(fptr), rawget<f32>(ptr),
rawget<f32>(fptr + 1), rawget<f32>(ptr + sizeof(f32)),
rawget<f32>(fptr + 2), rawget<f32>(ptr + 2 * sizeof(f32)),
rawget<f32>(fptr + 3)); rawget<f32>(ptr + 3 * sizeof(f32)));
} }
template <std::size_t N> template <std::size_t N>

@ -32,7 +32,7 @@ class CGLTFMeshFileLoader : public IMeshLoader
private: private:
template <typename T> template <typename T>
static T rawget(const void *ptr); static T rawget(const u8 *ptr);
template <class T> template <class T>
class Accessor class Accessor