| #ifndef EXAMPLE_GLTF_LOADER_H_ |
| #define EXAMPLE_GLTF_LOADER_H_ |
| |
| #include <stdexcept> |
| #include <string> |
| #include <vector> |
| |
| #include "material.h" |
| #include "mesh.h" |
| |
| namespace example { |
| |
| /// Adapts an array of bytes to an array of T. Will advace of byte_stride each |
| /// elements. |
| template <typename T> |
| struct arrayAdapter { |
| /// Pointer to the bytes |
| const unsigned char *dataPtr; |
| /// Number of elements in the array |
| const size_t elemCount; |
| /// Stride in bytes between two elements |
| const size_t stride; |
| |
| /// Construct an array adapter. |
| /// \param ptr Pointer to the start of the data, with offset applied |
| /// \param count Number of elements in the array |
| /// \param byte_stride Stride betweens elements in the array |
| arrayAdapter(const unsigned char *ptr, size_t count, size_t byte_stride) |
| : dataPtr(ptr), elemCount(count), stride(byte_stride) {} |
| |
| /// Returns a *copy* of a single element. Can't be used to modify it. |
| T operator[](size_t pos) const { |
| if (pos >= elemCount) |
| throw std::out_of_range( |
| "Tried to access beyond the last element of an array adapter with " |
| "count " + |
| std::to_string(elemCount) + " while getting elemnet number " + |
| std::to_string(pos)); |
| return *(reinterpret_cast<const T *>(dataPtr + pos * stride)); |
| } |
| }; |
| |
| /// Interface of any adapted array that returns ingeger data |
| struct intArrayBase { |
| virtual ~intArrayBase() = default; |
| virtual unsigned int operator[](size_t) const = 0; |
| virtual size_t size() const = 0; |
| }; |
| |
| /// Interface of any adapted array that returns float data |
| struct floatArrayBase { |
| virtual ~floatArrayBase() = default; |
| virtual float operator[](size_t) const = 0; |
| virtual size_t size() const = 0; |
| }; |
| |
| /// An array that loads interger types, returns them as int |
| template <class T> |
| struct intArray : public intArrayBase { |
| arrayAdapter<T> adapter; |
| |
| intArray(const arrayAdapter<T> &a) : adapter(a) {} |
| unsigned int operator[](size_t position) const override { |
| return static_cast<unsigned int>(adapter[position]); |
| } |
| |
| size_t size() const override { return adapter.elemCount; } |
| }; |
| |
| template <class T> |
| struct floatArray : public floatArrayBase { |
| arrayAdapter<T> adapter; |
| |
| floatArray(const arrayAdapter<T> &a) : adapter(a) {} |
| float operator[](size_t position) const override { |
| return static_cast<float>(adapter[position]); |
| } |
| |
| size_t size() const override { return adapter.elemCount; } |
| }; |
| |
| #pragma pack(push, 1) |
| |
| template <typename T> |
| struct v2 { |
| T x, y; |
| }; |
| /// 3D vector of floats without padding |
| template <typename T> |
| struct v3 { |
| T x, y, z; |
| }; |
| |
| /// 4D vector of floats without padding |
| template <typename T> |
| struct v4 { |
| T x, y, z, w; |
| }; |
| |
| #pragma pack(pop) |
| |
| using v2f = v2<float>; |
| using v3f = v3<float>; |
| using v4f = v4<float>; |
| using v2d = v2<double>; |
| using v3d = v3<double>; |
| using v4d = v4<double>; |
| |
| struct v2fArray { |
| arrayAdapter<v2f> adapter; |
| v2fArray(const arrayAdapter<v2f> &a) : adapter(a) {} |
| |
| v2f operator[](size_t position) const { return adapter[position]; } |
| size_t size() const { return adapter.elemCount; } |
| }; |
| |
| struct v3fArray { |
| arrayAdapter<v3f> adapter; |
| v3fArray(const arrayAdapter<v3f> &a) : adapter(a) {} |
| |
| v3f operator[](size_t position) const { return adapter[position]; } |
| size_t size() const { return adapter.elemCount; } |
| }; |
| |
| struct v4fArray { |
| arrayAdapter<v4f> adapter; |
| v4fArray(const arrayAdapter<v4f> &a) : adapter(a) {} |
| |
| v4f operator[](size_t position) const { return adapter[position]; } |
| size_t size() const { return adapter.elemCount; } |
| }; |
| |
| struct v2dArray { |
| arrayAdapter<v2d> adapter; |
| v2dArray(const arrayAdapter<v2d> &a) : adapter(a) {} |
| |
| v2d operator[](size_t position) const { return adapter[position]; } |
| size_t size() const { return adapter.elemCount; } |
| }; |
| |
| struct v3dArray { |
| arrayAdapter<v3d> adapter; |
| v3dArray(const arrayAdapter<v3d> &a) : adapter(a) {} |
| |
| v3d operator[](size_t position) const { return adapter[position]; } |
| size_t size() const { return adapter.elemCount; } |
| }; |
| |
| struct v4dArray { |
| arrayAdapter<v4d> adapter; |
| v4dArray(const arrayAdapter<v4d> &a) : adapter(a) {} |
| |
| v4d operator[](size_t position) const { return adapter[position]; } |
| size_t size() const { return adapter.elemCount; } |
| }; |
| |
| /// |
| /// Loads glTF 2.0 mesh |
| /// |
| bool LoadGLTF(const std::string &filename, float scale, |
| std::vector<Mesh<float> > *meshes, |
| std::vector<Material> *materials, std::vector<Texture> *textures); |
| |
| } // namespace example |
| |
| #endif // EXAMPLE_GLTF_LOADER_H_ |