@@ -41,7 +41,7 @@ void loadVertices(const fastgltf::Primitive& primitive,
41
41
const std::vector<fastgltf::Buffer>& buffers,
42
42
const std::vector<fastgltf::BufferView>& bufferViews,
43
43
const std::vector<fastgltf::Accessor>& accessors,
44
- std::vector<Vertex>& vertices ) {
44
+ Submesh& submesh ) {
45
45
Logger::debug (" [GltfLoad] Loading vertices..." );
46
46
47
47
const auto positionIt = primitive.findAttribute (" POSITION" );
@@ -54,6 +54,7 @@ void loadVertices(const fastgltf::Primitive& primitive,
54
54
if (!positionAccessor.bufferViewIndex .has_value ())
55
55
return ;
56
56
57
+ std::vector<Vertex>& vertices = submesh.getVertices ();
57
58
vertices.resize (positionAccessor.count );
58
59
59
60
loadVertexData<float >(positionAccessor, buffers, bufferViews, vertices, [] (Vertex& vert, const float * data) {
@@ -79,6 +80,8 @@ void loadVertices(const fastgltf::Primitive& primitive,
79
80
}}
80
81
}};
81
82
83
+ bool hasLoadedTangents = false ;
84
+
82
85
for (auto && [attribName, callback] : attributes) {
83
86
const auto attribIter = primitive.findAttribute (attribName);
84
87
@@ -87,10 +90,17 @@ void loadVertices(const fastgltf::Primitive& primitive,
87
90
88
91
const fastgltf::Accessor& attribAccessor = accessors[attribIter->second ];
89
92
90
- if (attribAccessor.bufferViewIndex .has_value ())
93
+ if (attribAccessor.bufferViewIndex .has_value ()) {
91
94
loadVertexData (attribAccessor, buffers, bufferViews, vertices, callback);
95
+
96
+ if (attribName == " TANGENT" )
97
+ hasLoadedTangents = true ;
98
+ }
92
99
}
93
100
101
+ if (!hasLoadedTangents)
102
+ submesh.computeTangents ();
103
+
94
104
Logger::debug (" [GltfLoad] Loaded vertices" );
95
105
}
96
106
@@ -117,19 +127,21 @@ void loadIndices(const fastgltf::Accessor& indicesAccessor,
117
127
const std::size_t dataStride = indicesView.byteStride .value_or (dataSize);
118
128
119
129
for (std::size_t i = 0 ; i < indices.size (); ++i) {
130
+ const uint8_t * const indexData = indicesData + i * dataStride;
131
+
120
132
// The indices must be of an unsigned integer type, but its size is unspecified
121
133
// See: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_mesh_primitive_indices
122
134
switch (dataSize) {
123
135
case 1 :
124
- indices[i] = *reinterpret_cast < const uint8_t *>(indicesData + i * dataStride) ;
136
+ indices[i] = *indexData ;
125
137
break ;
126
138
127
139
case 2 :
128
- indices[i] = *reinterpret_cast <const uint16_t *>(indicesData + i * dataStride );
140
+ indices[i] = *reinterpret_cast <const uint16_t *>(indexData );
129
141
break ;
130
142
131
143
case 4 :
132
- indices[i] = *reinterpret_cast <const uint32_t *>(indicesData + i * dataStride );
144
+ indices[i] = *reinterpret_cast <const uint32_t *>(indexData );
133
145
break ;
134
146
135
147
default :
@@ -157,8 +169,9 @@ std::pair<Mesh, MeshRenderer> loadMeshes(const std::vector<fastgltf::Mesh>& mesh
157
169
Submesh& submesh = loadedMesh.addSubmesh ();
158
170
SubmeshRenderer& submeshRenderer = loadedMeshRenderer.addSubmeshRenderer ();
159
171
160
- loadVertices (primitive, buffers, bufferViews, accessors, submesh. getVertices ());
172
+ // Indices must be loaded first as they are needed to compute the tangents if necessary
161
173
loadIndices (accessors[*primitive.indicesAccessor ], buffers, bufferViews, submesh.getTriangleIndices ());
174
+ loadVertices (primitive, buffers, bufferViews, accessors, submesh);
162
175
163
176
submeshRenderer.load (submesh, (primitive.type == fastgltf::PrimitiveType::Triangles ? RenderMode::TRIANGLE : RenderMode::POINT));
164
177
submeshRenderer.setMaterialIndex (primitive.materialIndex .value_or (0 ));
0 commit comments