From 2ddc86ff65aa93abc321f98996c2657e9fd2d712 Mon Sep 17 00:00:00 2001 From: Hill Ma Date: Sun, 11 Apr 2021 08:57:15 -0700 Subject: [PATCH] Fix model loading on big endian. --- src/model.cpp | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/model.cpp b/src/model.cpp index 944ee2a..eb0e428 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -29,6 +29,7 @@ #include "util.h" #include "float.h" #include "math.h" +#include #include #include #include @@ -39,12 +40,27 @@ using LibMatrix::vec2; using LibMatrix::vec3; using LibMatrix::uvec3; -#define read_or_fail(file, dst, size) do { \ - file.read(reinterpret_cast((dst)), (size)); \ - if (file.gcount() < (std::streamsize)(size)) { \ +static inline void read_from_file(std::istream& file, void *dst, size_t nmemb, size_t size) { + file.read(reinterpret_cast(dst), nmemb * size); +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + char *p = reinterpret_cast(dst); + for (size_t i = 0; i < nmemb; ++i) { + if (size == 2) { + std::swap(p[size*i], p[size*i+1]); + } else if (size == 4) { + std::swap(p[size*i], p[size*i+3]); + std::swap(p[size*i+1], p[size*i+2]); + } + } +#endif +} + +#define read_or_fail(file, dst, nmemb, size) do { \ + read_from_file((file), (dst), (nmemb), (size)); \ + if (file.gcount() < (std::streamsize)((nmemb)*(size))) { \ Log::error("%s: %d: Failed to read %zd bytes from 3ds file (read %zd)\n", \ __FUNCTION__, __LINE__, \ - (size_t)(size), file.gcount()); \ + (size_t)((nmemb)*(size)), file.gcount()); \ return false; \ } \ } while(0); @@ -375,7 +391,7 @@ Model::load_3ds(const std::string &filename) uint32_t chunk_length; // Read the chunk header - input_file.read(reinterpret_cast(&chunk_id), 2); + read_from_file(input_file, &chunk_id, 1, 2); if (input_file.gcount() == 0) { continue; } @@ -386,7 +402,7 @@ Model::load_3ds(const std::string &filename) } //Read the length of the chunk - read_or_fail(input_file, &chunk_length, 4); + read_or_fail(input_file, &chunk_length, 1, 4); switch (chunk_id) { @@ -417,7 +433,7 @@ Model::load_3ds(const std::string &filename) unsigned char c = 1; for (int i = 0; i < 20 && c != '\0'; i++) { - read_or_fail(input_file, &c, 1); + read_or_fail(input_file, &c, 1, 1); ss << c; } @@ -444,12 +460,12 @@ Model::load_3ds(const std::string &filename) case 0x4110: { uint16_t qty; - read_or_fail(input_file, &qty, sizeof(uint16_t)); + read_or_fail(input_file, &qty, 1, sizeof(uint16_t)); object->vertices.resize(qty); for (uint16_t i = 0; i < qty; i++) { float f[3]; - read_or_fail(input_file, f, sizeof(float) * 3); + read_or_fail(input_file, f, 3, sizeof(float)); vec3& vertex = object->vertices[i].v; vertex.x(f[0]); vertex.y(f[1]); @@ -468,11 +484,11 @@ Model::load_3ds(const std::string &filename) case 0x4120: { uint16_t qty; - read_or_fail(input_file, &qty, sizeof(uint16_t)); + read_or_fail(input_file, &qty, 1, sizeof(uint16_t)); object->faces.resize(qty); for (uint16_t i = 0; i < qty; i++) { uint16_t f[4]; - read_or_fail(input_file, f, sizeof(uint16_t) * 4); + read_or_fail(input_file, f, 4, sizeof(uint16_t)); uvec3& face = object->faces[i].v; face.x(f[0]); face.y(f[1]); @@ -491,10 +507,10 @@ Model::load_3ds(const std::string &filename) case 0x4140: { uint16_t qty; - read_or_fail(input_file, &qty, sizeof(uint16_t)); + read_or_fail(input_file, &qty, 1, sizeof(uint16_t)); for (uint16_t i = 0; i < qty; i++) { float f[2]; - read_or_fail(input_file, f, sizeof(float) * 2); + read_or_fail(input_file, f, 2, sizeof(float)); vec2& texcoord = object->vertices[i].t; texcoord.x(f[0]); texcoord.y(f[1]);