diff --git a/include/vector3d.h b/include/vector3d.h index 72a41f66..a69f17e1 100644 --- a/include/vector3d.h +++ b/include/vector3d.h @@ -7,7 +7,6 @@ #include "irrMath.h" #include -#include namespace irr { diff --git a/source/Irrlicht/CGLTFMeshFileLoader.cpp b/source/Irrlicht/CGLTFMeshFileLoader.cpp index 8bec5de2..899d95b4 100644 --- a/source/Irrlicht/CGLTFMeshFileLoader.cpp +++ b/source/Irrlicht/CGLTFMeshFileLoader.cpp @@ -34,19 +34,6 @@ * of the vertex indices. */ -// A helper function to disable tinygltf embedded image loading -static bool dummyImageLoader(tinygltf::Image *a, - const int b, std::string *c, - std::string *d, - int e, - int f, - const unsigned char * g, - int h, - void *userPointer) -{ - return false; -}; - namespace irr { namespace scene { @@ -67,6 +54,9 @@ CGLTFMeshFileLoader::BufferOffset::BufferOffset( { } +/** + * Get a raw unsigned char (ubyte) from a buffer offset. +*/ unsigned char CGLTFMeshFileLoader::BufferOffset::at( const std::size_t fromOffset) const { @@ -77,12 +67,18 @@ CGLTFMeshFileLoader::CGLTFMeshFileLoader() noexcept { } +/** + * The most basic portion of the code base. This tells irllicht if this file has a .gltf extension. +*/ bool CGLTFMeshFileLoader::isALoadableFileExtension( const io::path& filename) const { return core::hasFileExtension(filename, "gltf"); } +/** + * Entry point into loading a GLTF model. +*/ IAnimatedMesh* CGLTFMeshFileLoader::createMesh(io::IReadFile* file) { tinygltf::Model model {}; @@ -101,6 +97,12 @@ IAnimatedMesh* CGLTFMeshFileLoader::createMesh(io::IReadFile* file) return animatedMesh; } + +/** + * Load up the rawest form of the model. The vertex positions and indices. + * Documentation: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#meshes + * If material is undefined, then a default material MUST be used. +*/ void CGLTFMeshFileLoader::loadPrimitives( const MeshExtractor& parser, SMesh* mesh) @@ -130,6 +132,9 @@ CGLTFMeshFileLoader::MeshExtractor::MeshExtractor( { } +/** + * Extracts GLTF mesh indices into the irrlicht model. +*/ std::vector CGLTFMeshFileLoader::MeshExtractor::getIndices( const std::size_t meshIdx, const std::size_t primitiveIdx) const @@ -148,6 +153,9 @@ std::vector CGLTFMeshFileLoader::MeshExtractor::getIndices( return indices; } +/** + * Create a vector of video::S3DVertex (model data) from a mesh & primitive index. +*/ std::vector CGLTFMeshFileLoader::MeshExtractor::getVertices( const std::size_t meshIdx, const std::size_t primitiveIdx) const @@ -173,18 +181,30 @@ std::vector CGLTFMeshFileLoader::MeshExtractor::getVertices( return vertices; } +/** + * Get the amount of meshes that a model contains. +*/ std::size_t CGLTFMeshFileLoader::MeshExtractor::getMeshCount() const { return m_model.meshes.size(); } +/** + * Get the amount of primitives that a mesh in a model contains. +*/ std::size_t CGLTFMeshFileLoader::MeshExtractor::getPrimitiveCount( const std::size_t meshIdx) const { return m_model.meshes[meshIdx].primitives.size(); } - +/** + * Templated buffer reader. Based on type width. + * This is specifically used to build upon to read more complex data types. + * It is also used raw to read arrays directly. + * Basically we're using the width of the type to infer + * how big of a gap we have from the beginning of the buffer. +*/ template T CGLTFMeshFileLoader::MeshExtractor::readPrimitive( const BufferOffset& readFrom) @@ -198,6 +218,10 @@ T CGLTFMeshFileLoader::MeshExtractor::readPrimitive( return dest; } +/** + * Read a vector2df from a buffer at an offset. + * @return vec2 core::Vector2df +*/ core::vector2df CGLTFMeshFileLoader::MeshExtractor::readVec2DF( const CGLTFMeshFileLoader::BufferOffset& readFrom) { @@ -206,9 +230,13 @@ core::vector2df CGLTFMeshFileLoader::MeshExtractor::readVec2DF( } +/** + * Read a vector3df from a buffer at an offset. + * @return vec3 core::Vector3df +*/ core::vector3df CGLTFMeshFileLoader::MeshExtractor::readVec3DF( const BufferOffset& readFrom, - const float scale) + const float scale = 1.0f) { return core::vector3df( scale * readPrimitive(readFrom), @@ -217,6 +245,10 @@ core::vector3df CGLTFMeshFileLoader::MeshExtractor::readVec3DF( sizeof(float)))); } +/** + * Streams vertex positions raw data into usable buffer via reference. + * Buffer: ref Vector +*/ void CGLTFMeshFileLoader::MeshExtractor::copyPositions( const std::size_t accessorIdx, std::vector& vertices) const @@ -233,6 +265,10 @@ void CGLTFMeshFileLoader::MeshExtractor::copyPositions( } } +/** + * Streams normals raw data into usable buffer via reference. + * Buffer: ref Vector +*/ void CGLTFMeshFileLoader::MeshExtractor::copyNormals( const std::size_t accessorIdx, std::vector& vertices) const @@ -247,10 +283,15 @@ void CGLTFMeshFileLoader::MeshExtractor::copyNormals( } } +/** + * Streams texture coordinate raw data into usable buffer via reference. + * Buffer: ref Vector +*/ void CGLTFMeshFileLoader::MeshExtractor::copyTCoords( const std::size_t accessorIdx, std::vector& vertices) const { + const auto& buffer = getBuffer(accessorIdx); const auto count = getElemCount(accessorIdx); @@ -261,6 +302,13 @@ void CGLTFMeshFileLoader::MeshExtractor::copyTCoords( } } +/** + * Gets the scale of a model's node via a reference Vector3df. + * Documentation: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-node + * Type: number[3] (tinygltf: vector) + * Required: NO + * @returns: core::vector2df +*/ float CGLTFMeshFileLoader::MeshExtractor::getScale() const { if (m_model.nodes[0].scale.size() > 0) { @@ -270,12 +318,25 @@ float CGLTFMeshFileLoader::MeshExtractor::getScale() const return 1.0f; } +/** + * The number of elements referenced by this accessor, not to be confused with the number of bytes or number of components. + * Documentation: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_accessor_count + * Type: Integer + * Required: YES +*/ std::size_t CGLTFMeshFileLoader::MeshExtractor::getElemCount( const std::size_t accessorIdx) const { return m_model.accessors[accessorIdx].count; } +/** + * The stride, in bytes, between vertex attributes. + * When this is not defined, data is tightly packed. + * When two or more accessors use the same buffer view, this field MUST be defined. + * Documentation: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_bufferview_bytestride + * Required: NO +*/ std::size_t CGLTFMeshFileLoader::MeshExtractor::getByteStride( const std::size_t accessorIdx) const { @@ -284,6 +345,24 @@ std::size_t CGLTFMeshFileLoader::MeshExtractor::getByteStride( return accessor.ByteStride(view); } +/** + * Specifies whether integer data values are normalized (true) to [0, 1] (for unsigned types) + * or to [-1, 1] (for signed types) when they are accessed. This property MUST NOT be set to + * true for accessors with FLOAT or UNSIGNED_INT component type. + * Documentation: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_accessor_normalized + * Required: NO +*/ +bool CGLTFMeshFileLoader::MeshExtractor::isAccessorNormalized( + const std::size_t accessorIdx) const +{ + const auto& accessor = m_model.accessors[accessorIdx]; + return accessor.normalized; +} + +/** + * Walk through the complex chain of the model to extract the required buffer. + * Accessor -> BufferView -> Buffer +*/ CGLTFMeshFileLoader::BufferOffset CGLTFMeshFileLoader::MeshExtractor::getBuffer( const std::size_t accessorIdx) const { @@ -294,6 +373,14 @@ CGLTFMeshFileLoader::BufferOffset CGLTFMeshFileLoader::MeshExtractor::getBuffer( return BufferOffset(buffer.data, view.byteOffset); } +/** + * The index of the accessor that contains the vertex indices. + * When this is undefined, the primitive defines non-indexed geometry. + * When defined, the accessor MUST have SCALAR type and an unsigned integer component type. + * Documentation: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_mesh_primitive_indices + * Type: Integer + * Required: NO +*/ std::size_t CGLTFMeshFileLoader::MeshExtractor::getIndicesAccessorIdx( const std::size_t meshIdx, const std::size_t primitiveIdx) const @@ -301,6 +388,12 @@ std::size_t CGLTFMeshFileLoader::MeshExtractor::getIndicesAccessorIdx( return m_model.meshes[meshIdx].primitives[primitiveIdx].indices; } +/** + * The index of the accessor that contains the POSITIONs. + * Documentation: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#meshes-overview + * Type: VEC3 (Float) + * ! Required: YES (Appears so, needs another pair of eyes to research.) +*/ std::size_t CGLTFMeshFileLoader::MeshExtractor::getPositionAccessorIdx( const std::size_t meshIdx, const std::size_t primitiveIdx) const @@ -309,6 +402,12 @@ std::size_t CGLTFMeshFileLoader::MeshExtractor::getPositionAccessorIdx( .attributes.find("POSITION")->second; } +/** + * The index of the accessor that contains the NORMALs. + * Documentation: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#meshes-overview + * Type: VEC3 (Float) + * ! Required: NO (Appears to not be, needs another pair of eyes to research.) +*/ std::size_t CGLTFMeshFileLoader::MeshExtractor::getNormalAccessorIdx( const std::size_t meshIdx, const std::size_t primitiveIdx) const @@ -324,6 +423,12 @@ std::size_t CGLTFMeshFileLoader::MeshExtractor::getNormalAccessorIdx( } } +/** + * The index of the accessor that contains the NORMALs. + * Documentation: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#meshes-overview + * Type: VEC3 (Float) + * ! Required: YES (Appears so, needs another pair of eyes to research.) +*/ std::size_t CGLTFMeshFileLoader::MeshExtractor::getTCoordAccessorIdx( const std::size_t meshIdx, const std::size_t primitiveIdx) const @@ -339,13 +444,16 @@ std::size_t CGLTFMeshFileLoader::MeshExtractor::getTCoordAccessorIdx( } } +/** + * This is where the actual model's GLTF file is loaded and parsed by tinygltf. +*/ bool CGLTFMeshFileLoader::tryParseGLTF(io::IReadFile* file, tinygltf::Model& model) { tinygltf::TinyGLTF loader {}; // Stop embedded textures from making model fail to load - loader.SetImageLoader(dummyImageLoader, nullptr); + loader.SetImageLoader(nullptr, nullptr); std::string err {}; std::string warn {}; diff --git a/source/Irrlicht/CGLTFMeshFileLoader.h b/source/Irrlicht/CGLTFMeshFileLoader.h index 2f141168..3e03ce1d 100644 --- a/source/Irrlicht/CGLTFMeshFileLoader.h +++ b/source/Irrlicht/CGLTFMeshFileLoader.h @@ -85,7 +85,7 @@ private: */ static core::vector3df readVec3DF( const BufferOffset& readFrom, - const float scale = 1.0f); + const float scale); void copyPositions(const std::size_t accessorIdx, std::vector& vertices) const; @@ -98,7 +98,7 @@ private: /* Get the scale factor from the glTF mesh information. * - * Returns 1.0f if no scale factor is present. + * Returns vec3(1.0, 1.0, 1.0) if no scale factor is present. */ float getScale() const; @@ -106,6 +106,8 @@ private: std::size_t getByteStride(const std::size_t accessorIdx) const; + bool isAccessorNormalized(const std::size_t accessorIdx) const; + BufferOffset getBuffer(const std::size_t accessorIdx) const; std::size_t getIndicesAccessorIdx(const std::size_t meshIdx,