Package glTF spec docs with comments

* git --CRUSH

And try to make this line the same

Now undo my gitignore nonsense

Hail mary

Move these functions to the top

More documentation

Add some serious documentation

Move this to the top

Readability & documentation

Add some documentation

Add spec documentation

Make this more more complex to make it less complex

Move this up & document

Make this more readable for me

Document and make this more readable

Move this out of the way and document it

Update CGLTFMeshFileLoader.cpp

Documentation

Document

Update CGLTFMeshFileLoader.cpp

Document

Move entry point to bottom

Part 5

Part 4

Part 3

Part 2

Allman -> OTBS (readability for me)

Consolidate

Remove unneeded function

These files are annoying

* fix #1

* fix 2

* indentation

* Remove redundant function

* Remove redundant function

* add trailing new line

* Stop an interesting build error with a template

* Code reduction

* Document bytestride

* Add more detail to chain hierarchy

* Dump this huge vscode thing in here for no reason

* Document 3 more functions

* Document copyTcoords

* Dump in (incorrect) scale documentation for node

* Add a readable description

* Fix incorrect getScale

* Add update based on context of function

* Add documentation, fix another one

* Document another

* Document another

* And document another

* Document this nice function

* Bolt in some future use documentation

* Add highlighting for IDE

* Just shovel on more docs to this

* 2 more comments

* I think that's all of them

* Add some wild west debuggin

* And then update this comment

* Bolt on isAccessorNormalized()

* Bolt in an absolute hack job to test

* Now clean this mess up and give josiah ref material

* Fix Josiah's request for scale

* Fix josiah request

* Fix josiah request .vscode

Fix indentation

Fix indentation

Fix indentation

* Unfix getScale()

again
This commit is contained in:
jordan4ibanez 2023-12-01 17:10:01 -05:00 committed by Josiah VanderZee
parent 95a4030b50
commit f8f10248b4
3 changed files with 128 additions and 19 deletions

View File

@ -7,7 +7,6 @@
#include "irrMath.h"
#include <functional>
#include <ostream>
namespace irr
{

View File

@ -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<u16> CGLTFMeshFileLoader::MeshExtractor::getIndices(
const std::size_t meshIdx,
const std::size_t primitiveIdx) const
@ -148,6 +153,9 @@ std::vector<u16> CGLTFMeshFileLoader::MeshExtractor::getIndices(
return indices;
}
/**
* Create a vector of video::S3DVertex (model data) from a mesh & primitive index.
*/
std::vector<video::S3DVertex> CGLTFMeshFileLoader::MeshExtractor::getVertices(
const std::size_t meshIdx,
const std::size_t primitiveIdx) const
@ -173,18 +181,30 @@ std::vector<video::S3DVertex> 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 <typename T>
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<float>(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<video::S3DVertex>
*/
void CGLTFMeshFileLoader::MeshExtractor::copyPositions(
const std::size_t accessorIdx,
std::vector<vertex_t>& vertices) const
@ -233,6 +265,10 @@ void CGLTFMeshFileLoader::MeshExtractor::copyPositions(
}
}
/**
* Streams normals raw data into usable buffer via reference.
* Buffer: ref Vector<video::S3DVertex>
*/
void CGLTFMeshFileLoader::MeshExtractor::copyNormals(
const std::size_t accessorIdx,
std::vector<vertex_t>& vertices) const
@ -247,10 +283,15 @@ void CGLTFMeshFileLoader::MeshExtractor::copyNormals(
}
}
/**
* Streams texture coordinate raw data into usable buffer via reference.
* Buffer: ref Vector<video::S3DVertex>
*/
void CGLTFMeshFileLoader::MeshExtractor::copyTCoords(
const std::size_t accessorIdx,
std::vector<vertex_t>& 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<double>)
* 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 {};

View File

@ -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<vertex_t>& 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,