From 5682cb45427a321c7a045f05c3db2daf23fa5113 Mon Sep 17 00:00:00 2001 From: Arthur Brainville Date: Mon, 19 Feb 2018 23:44:31 +0100 Subject: [PATCH] Also access the position attribute of the primitive Signed-off-by: Arthur Brainville (Ybalrid) --- examples/raytrace/gltf-loader.cc | 201 +++++++++++++++++++++++-------- 1 file changed, 148 insertions(+), 53 deletions(-) diff --git a/examples/raytrace/gltf-loader.cc b/examples/raytrace/gltf-loader.cc index 91434b2..b17d848 100644 --- a/examples/raytrace/gltf-loader.cc +++ b/examples/raytrace/gltf-loader.cc @@ -2,9 +2,12 @@ #include #include // c++11 +#include #define TINYGLTF_IMPLEMENTATION #include +using std::out_of_range; + namespace example { static std::string GetFilePathExtension(const std::string &FileName) { @@ -13,38 +16,50 @@ static std::string GetFilePathExtension(const std::string &FileName) { return ""; } +/// Adapts an array of bytes to an array of T. Will advace of byte_stride each +/// elements. template struct arrayAdapter { - unsigned char *dataPtr; + /// 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; - arrayAdapter(unsigned char *ptr, size_t count, size_t byte_stride = 1) + /// Constructor. + arrayAdapter(const unsigned char *ptr, size_t count, size_t byte_stride = 1) : dataPtr(ptr), elemCount(count), stride(byte_stride) {} - T operator[](size_t pos) { + /// 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( + throw out_of_range( "Tried to access beyond the last element of an array adapter"); - return *(reinterpret_cast(dataPtr + pos * stride)); + return *(reinterpret_cast(dataPtr + pos * stride)); } }; +/// Interface of any adapted array that returns ingeger data struct intArrayBase { - virtual int operator[](size_t) = 0; + virtual ~intArrayBase() = default; + virtual int operator[](size_t) const = 0; virtual size_t size() const = 0; }; +/// Interface of any adapted array that returns float data struct floatArrayBase { - virtual float operator[](size_t) = 0; + 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 struct intArray : public intArrayBase { arrayAdapter adapter; intArray(const arrayAdapter &a) : adapter(a) {} - int operator[](size_t position) override { + int operator[](size_t position) const override { return static_cast(adapter[position]); } @@ -56,13 +71,56 @@ struct floatArray : public floatArrayBase { arrayAdapter adapter; floatArray(const arrayAdapter &a) : adapter(a) {} - float operator[](size_t position) override { + float operator[](size_t position) const override { return static_cast(adapter[position]); } size_t size() const override { return adapter.elemCount; } }; +#pragma pack(push, 1) + +template +struct v2 { + T x, y; +}; +/// 3D vector of floats without padding +template +struct v3 { + T x, y, z; +}; + +/// 4D vector of floats without padding +template +struct v4 { + T x, y, z, w; +}; + +#pragma pack(pop) + +using v2f = v2; +using v3f = v3; +using v4f = v4; +using v2d = v2; +using v3d = v3; +using v4d = v4; + +struct v3fArray { + arrayAdapter adapter; + v3fArray(const arrayAdapter &a) : adapter(a) {} + + v3f operator[](size_t position) const { return adapter[position]; } + size_t size() const { return adapter.elemCount; } +}; + +struct v4fArray { + arrayAdapter adapter; + v4fArray(const arrayAdapter &a) : adapter(a) {} + + v4f operator[](size_t position) const { return adapter[position]; } + size_t size() const { return adapter.elemCount; } +}; + /// /// Loads glTF 2.0 mesh /// @@ -120,56 +178,61 @@ bool LoadGLTF(const std::string &filename, float scale, loadedMesh.name = gltfMesh.name; for (const auto &meshPrimitive : gltfMesh.primitives) { // get access to the indices - std::unique_ptr indicesArray = nullptr; + std::unique_ptr indicesArrayPtr = nullptr; + { + auto &indicesAccessor = model.accessors[meshPrimitive.indices]; + auto &bufferView = model.bufferViews[indicesAccessor.bufferView]; + auto &buffer = model.buffers[bufferView.buffer]; + unsigned char *dataAddress = buffer.data.data() + + bufferView.byteOffset + + indicesAccessor.byteOffset; + const auto byteStride = indicesAccessor.ByteStride(bufferView); + const auto count = indicesAccessor.count; - auto &indicesAccessor = model.accessors[meshPrimitive.indices]; - auto &bufferView = model.bufferViews[indicesAccessor.bufferView]; - auto &buffer = model.buffers[bufferView.buffer]; - unsigned char *dataAddress = buffer.data.data() + bufferView.byteOffset + - indicesAccessor.byteOffset; - const auto byteStride = indicesAccessor.ByteStride(bufferView); - const auto count = indicesAccessor.count; + switch (indicesAccessor.componentType) { + case TINYGLTF_COMPONENT_TYPE_BYTE: + indicesArrayPtr = + std::unique_ptr >(new intArray( + arrayAdapter(dataAddress, count, byteStride))); + break; - switch (indicesAccessor.componentType) { - case TINYGLTF_COMPONENT_TYPE_BYTE: - indicesArray = std::unique_ptr >(new intArray( - arrayAdapter(dataAddress, count, byteStride))); - break; + case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE: + indicesArrayPtr = std::unique_ptr >( + new intArray(arrayAdapter( + dataAddress, count, byteStride))); + break; - case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE: - indicesArray = std::unique_ptr >( - new intArray( - arrayAdapter(dataAddress, count, byteStride))); - break; + case TINYGLTF_COMPONENT_TYPE_SHORT: + indicesArrayPtr = + std::unique_ptr >(new intArray( + arrayAdapter(dataAddress, count, byteStride))); + break; - case TINYGLTF_COMPONENT_TYPE_SHORT: - indicesArray = std::unique_ptr >(new intArray( - arrayAdapter(dataAddress, count, byteStride))); - break; + case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT: + indicesArrayPtr = std::unique_ptr >( + new intArray(arrayAdapter( + dataAddress, count, byteStride))); + break; - case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT: - indicesArray = std::unique_ptr >( - new intArray(arrayAdapter( - dataAddress, count, byteStride))); - break; + case TINYGLTF_COMPONENT_TYPE_INT: + indicesArrayPtr = std::unique_ptr >(new intArray( + arrayAdapter(dataAddress, count, byteStride))); + break; - case TINYGLTF_COMPONENT_TYPE_INT: - indicesArray = std::unique_ptr >(new intArray( - arrayAdapter(dataAddress, count, byteStride))); - break; - - case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT: - indicesArray = std::unique_ptr >( - new intArray( - arrayAdapter(dataAddress, count, byteStride))); - break; - default: - break; + case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT: + indicesArrayPtr = std::unique_ptr >( + new intArray(arrayAdapter( + dataAddress, count, byteStride))); + break; + default: + break; + } } + const auto &indices = *indicesArrayPtr; - if (indicesArray) - for (size_t i(0); i < indicesArray->size(); ++i) { - std::cout << (*indicesArray)[i] << " "; + if (indicesArrayPtr) + for (size_t i(0); i < indicesArrayPtr->size(); ++i) { + std::cout << indices[i] << " "; } std::cout << '\n'; @@ -181,9 +244,41 @@ bool LoadGLTF(const std::string &filename, float scale, std::cout << "Will load a plain old list of trianges\n"; for (const auto &attribute : meshPrimitive.attributes) { + const auto attribAccessor = model.accessors[attribute.second]; + const auto &bufferView = + model.bufferViews[attribAccessor.bufferView]; + const auto &buffer = model.buffers[bufferView.buffer]; + auto dataPtr = buffer.data.data() + bufferView.byteOffset + + attribAccessor.byteOffset; + const auto byte_stride = attribAccessor.ByteStride(bufferView); + const auto count = attribAccessor.count; + if (attribute.first == "POSITION") { std::cout << "found position attribute\n"; - const auto posAccessor = model.accessors[attribute.second]; + + switch (attribAccessor.componentType) { + case TINYGLTF_COMPONENT_TYPE_FLOAT: + switch (attribAccessor.type) { + case TINYGLTF_TYPE_VEC3: { + /// 3D vector of float + v3fArray positions( + arrayAdapter(dataPtr, count, byte_stride)); + for (size_t i{0}; i < indices.size(); ++i) { + const auto index{indices[i]}; + const auto v = positions[index]; + std::cout << '(' << v.x << ", " << v.y << ", " << v.z + << ")\n"; + } + } break; + default: + // TODO Handle error + break; + } + break; + default: + // TODO handle error + break; + } } if (attribute.first == "NORMAL") { @@ -213,4 +308,4 @@ bool LoadGLTF(const std::string &filename, float scale, std::cerr << "LoadGLTF() function is not yet implemented!" << std::endl; return false; } -} // namespace example \ No newline at end of file +} // namespace example