SpiecsEngine
 
Loading...
Searching...
No Matches
GltfLoader.cpp
Go to the documentation of this file.
1/**
2* @file GltfLoader.cpp.
3* @brief The GltfLoader Class Implementation.
4* @author Spices.
5*/
6
7#include "Pchheader.h"
8#include "GltfLoader.h"
9#include "../Mesh/GltfPack.h"
10
11#include <nlohmann/json.hpp>
12
13namespace Spices {
14
15 using Json = nlohmann::json;
16
17 bool GltfLoader::Load(const std::string& fileName, GltfCollection* collection)
18 {
20
21 std::ifstream f(fileName);
22 if (!f)
23 {
24 std::stringstream ss;
25 ss << "Gltf File: " << fileName << " is not found.";
26
27 SPICES_CORE_ERROR(ss.str())
28 return false;
29 }
30
31 Json data;
32 f >> data;
33
34 std::filesystem::path parentPath = std::filesystem::path(fileName).parent_path();
35
36 SPICES_CORE_INFO("----------------------------------------------------------------");
37
38 if(data.find("asset") != data.end()) collection->m_Asset = std::make_unique<GltfAsset >(data["asset"]);
39 if(data.find("accessors") != data.end()) collection->m_Accessors = std::make_unique<GltfAccessors >(data["accessors"]);
40 if(data.find("buffers") != data.end()) collection->m_Buffers = std::make_unique<GltfBuffers >(data["buffers"], parentPath);
41 if(data.find("bufferViews") != data.end()) collection->m_BufferViews = std::make_unique<GltfBufferViews>(data["bufferViews"]);
42
43 if(data.find("images") != data.end()) collection->m_Images = std::make_unique<GltfImages >(data["images"], parentPath);
44 if(data.find("materials") != data.end()) collection->m_Materials = std::make_unique<GltfMaterials >(data["materials"]);
45 if(data.find("meshes") != data.end()) collection->m_Meshes = std::make_unique<GltfMeshes >(data["meshes"]);
46 if(data.find("nodes") != data.end()) collection->m_Nodes = std::make_unique<GltfNodes >(data["nodes"]);
47 if(data.find("samplers") != data.end()) collection->m_Samplers = std::make_unique<GltfSamplers >(data["samplers"]);
48 if(data.find("scene") != data.end()) collection->m_Scene = std::make_unique<GltfScene >(data["scene"]);
49 if(data.find("scenes") != data.end()) collection->m_Scenes = std::make_unique<GltfScenes >(data["scenes"]);
50 if(data.find("textures") != data.end()) collection->m_Textures = std::make_unique<GltfTextures >(data["textures"]);
51
52 SPICES_CORE_INFO("----------------------------------------------------------------");
53
54 return true;
55 }
56
57 bool GltfLoader::LoadPack(GltfPack* pack, const GltfMeshes::Primitive& primitive, GltfAccessors* accessors, GltfBuffers* buffers, GltfBufferViews* bufferViews)
58 {
60
61 // Positions
62 {
63 if (primitive.POSITION < 0)
64 {
65 SPICES_CORE_ERROR("Positions buffer invalid.")
66 return false;
67 }
68 const GltfAccessors::Item& positionAccessor = accessors->m_AccessorsData[primitive.POSITION];
69 const GltfBufferViews::Item& positionBufferView = bufferViews->m_BufferViewsData[positionAccessor.bufferView];
70 const GltfBuffers::Item& positionBuffer = buffers->m_BuffersData[positionBufferView.buffer];
71
72 const VkFormat format = GltfHelper::GetFormat(positionAccessor.type, positionAccessor.componentType);
73 const uint32_t bytes = GltfHelper::SizeOfFormat(format);
74
75 pack->m_MeshResource.positions.attributes->resize(positionAccessor.count);
76 for (uint32_t i = 0; i < pack->m_MeshResource.positions.attributes->size(); i++)
77 {
78 const uint32_t offset = i * bytes;
79
80 auto p = reinterpret_cast<glm::vec3*>(&(*positionBuffer.buffer)[positionAccessor.byteOffset + positionBufferView.byteOffset + offset]);
81 (*pack->m_MeshResource.positions.attributes)[i] = *p;
82
83 glm::vec3& pos = (*pack->m_MeshResource.positions.attributes)[i];
84 pos.z = -pos.z;
85 }
86 }
87
88 // Normals
89 bool hasNormal = false;
90 {
91 if (primitive.NORMAL < 0)
92 {
93 pack->m_MeshResource.normals.attributes->resize(1);
94 (*pack->m_MeshResource.normals.attributes)[0] = glm::vec3(0.0f, 1.0f, 0.0f);
95 }
96 else
97 {
98 hasNormal = true;
99
100 const GltfAccessors::Item& normalAccessor = accessors->m_AccessorsData[primitive.NORMAL];
101 const GltfBufferViews::Item& normalBufferView = bufferViews->m_BufferViewsData[normalAccessor.bufferView];
102 const GltfBuffers::Item& normalBuffer = buffers->m_BuffersData[normalBufferView.buffer];
103
104 const VkFormat format = GltfHelper::GetFormat(normalAccessor.type, normalAccessor.componentType);
105 const uint32_t bytes = GltfHelper::SizeOfFormat(format);
106
107 pack->m_MeshResource.normals.attributes->resize(normalAccessor.count);
108 for (uint32_t i = 0; i < pack->m_MeshResource.normals.attributes->size(); i++)
109 {
110 const uint32_t offset = i * bytes;
111
112 auto n = reinterpret_cast<glm::vec3*>(&(*normalBuffer.buffer)[normalAccessor.byteOffset + normalBufferView.byteOffset + offset]);
113 (*pack->m_MeshResource.normals.attributes)[i] = *n;
114
115 glm::vec3& nor = (*pack->m_MeshResource.normals.attributes)[i];
116 nor.z = -nor.z;
117 }
118 }
119 }
120
121 // Colors
122 bool hasColor = false;
123 {
124 pack->m_MeshResource.colors.attributes->resize(1);
125 (*pack->m_MeshResource.colors.attributes)[0] = glm::vec3(0.0f);
126 }
127
128 // TexCoords
129 bool hasTexCoords = false;
130 {
131 if (primitive.TEXCOORD_0 < 0)
132 {
133 pack->m_MeshResource.texCoords.attributes->resize(1);
134 (*pack->m_MeshResource.texCoords.attributes)[0] = glm::vec2(0.0f);
135 }
136 else
137 {
138 hasTexCoords = true;
139
140 const GltfAccessors::Item& texCoordAccessor = accessors->m_AccessorsData[primitive.TEXCOORD_0];
141 const GltfBufferViews::Item& texCoordBufferView = bufferViews->m_BufferViewsData[texCoordAccessor.bufferView];
142 const GltfBuffers::Item& texCoordBuffer = buffers->m_BuffersData[texCoordBufferView.buffer];
143
144 const VkFormat format = GltfHelper::GetFormat(texCoordAccessor.type, texCoordAccessor.componentType);
145 const uint32_t bytes = GltfHelper::SizeOfFormat(format);
146
147 pack->m_MeshResource.texCoords.attributes->resize(texCoordAccessor.count);
148 for (uint32_t i = 0; i < pack->m_MeshResource.texCoords.attributes->size(); i++)
149 {
150 const uint32_t offset = i * bytes;
151
152 auto u = reinterpret_cast<glm::vec2*>(&(*texCoordBuffer.buffer)[texCoordAccessor.byteOffset + texCoordBufferView.byteOffset + offset]);
153 (*pack->m_MeshResource.texCoords.attributes)[i] = *u;
154
155 glm::vec2& uv = (*pack->m_MeshResource.texCoords.attributes)[i];
156 //uv.y = 1.0f - uv.y;
157 }
158 }
159 }
160
161 // Vertices
162 {
163 const GltfAccessors::Item& positionAccessor = accessors->m_AccessorsData[primitive.POSITION];
164
165 pack->m_MeshResource.vertices.attributes->resize(positionAccessor.count);
166
167 for(uint32_t i = 0; i < pack->m_MeshResource.vertices.attributes->size(); i++)
168 {
169 (*pack->m_MeshResource.vertices.attributes)[i] = glm::uvec4(i, hasNormal ? i : 0, hasColor ? i : 0, hasTexCoords ? i: 0);
170 }
171 }
172
173 // primVertices
174 {
175 if (primitive.indices < 0)
176 {
177 SPICES_CORE_ERROR("indices buffer invalid.")
178 return false;
179 }
180 const GltfAccessors::Item& indicesAccessor = accessors->m_AccessorsData[primitive.indices];
181 const GltfBufferViews::Item& indicesBufferView = bufferViews->m_BufferViewsData[indicesAccessor.bufferView];
182 const GltfBuffers::Item& indicesBuffer = buffers->m_BuffersData[indicesBufferView.buffer];
183
184 const VkFormat format = GltfHelper::GetFormat(indicesAccessor.type, indicesAccessor.componentType);
185 const uint32_t bytes = GltfHelper::SizeOfFormat(format);
186
187 pack->m_MeshResource.primitiveVertices.attributes->resize(indicesAccessor.count / 3);
188 for (uint32_t i = 0; i < pack->m_MeshResource.primitiveVertices.attributes->size(); i++)
189 {
190 const uint32_t offset = i * 3 * bytes;
191
192 auto x = reinterpret_cast<unsigned short*>(&(*indicesBuffer.buffer)[indicesAccessor.byteOffset + indicesBufferView.byteOffset + offset + 0]);
193 auto y = reinterpret_cast<unsigned short*>(&(*indicesBuffer.buffer)[indicesAccessor.byteOffset + indicesBufferView.byteOffset + offset + bytes]);
194 auto z = reinterpret_cast<unsigned short*>(&(*indicesBuffer.buffer)[indicesAccessor.byteOffset + indicesBufferView.byteOffset + offset + bytes * 2]);
195
196 (*pack->m_MeshResource.primitiveVertices.attributes)[i] = glm::uvec3(*x, *y, *z);
197 }
198 }
199
200 return true;
201 }
202
203 std::shared_ptr<Material> GltfLoader::LoadMaterial(const GltfMaterials::Item& material, GltfImages* images)
204 {
206
207 std::stringstream ss;
208 ss << "BasePassRenderer.Mesh." << material.name;
209
210 if(ResourcePool<Material>::Has(ss.str()))
211 {
212 return ResourcePool<Material>::Access(ss.str());
213 }
214
215 auto outMaterial = std::make_shared<Material>();
216
217 outMaterial->SetName(ss.str());
218
219 outMaterial->PushToShaderPath("task", "BasePassRenderer.Mesh.Default");
220 outMaterial->PushToShaderPath("mesh", "BasePassRenderer.Mesh.Default");
221 outMaterial->PushToShaderPath("frag", "BasePassRenderer.Mesh.PBRGltf");
222 outMaterial->PushToShaderPath("rchit", "BasePassRenderer.Mesh.PBRGltf");
223
224 outMaterial->PushToTextureParams("baseColorTexture", {"Texture2D", material.baseColorTexture.has_value() ? images->m_ImagesData[material.baseColorTexture.value()].uri : "" });
225 outMaterial->PushToTextureParams("metallicRoughnessTexture", {"Texture2D", material.metallicRoughnessTexture.has_value() ? images->m_ImagesData[material.metallicRoughnessTexture.value()].uri : "" });
226 outMaterial->PushToTextureParams("normalTexture", {"Texture2D", material.normalTexture.has_value() ? images->m_ImagesData[material.normalTexture.value()].uri : ""});
227 outMaterial->PushToTextureParams("emissiveTexture", {"Texture2D", material.emissiveTexture.has_value() ? images->m_ImagesData[material.emissiveTexture.value()].uri : "" });
228 outMaterial->PushToTextureParams("occlusionTexture", {"Texture2D", material.occlusionTexture.has_value() ? images->m_ImagesData[material.occlusionTexture.value()].uri : "" });
229
230 outMaterial->PushToConstParams("baseColorFactor", {"float4", material.baseColorFactor});
231 outMaterial->PushToConstParams("emissiveFactor", {"float4", material.emissiveFactor});
232
233 outMaterial->PushToConstParams("maxRayDepth", {"int", 3});
234 outMaterial->PushToConstParams("maxLightDepth", {"int", 2});
235 outMaterial->PushToConstParams("maxShadowDepth", {"int", 1});
236
237 ResourcePool<Material>::Registry(ss.str(), outMaterial);
238
239 return ResourcePool<Material>::Access(ss.str());
240 }
241}
#define SPICES_PROFILE_ZONE
Wrapper of Gltf Json Accessors.
Wrapper of Gltf Json BufferViews.
Wrapper of Gltf Json Buffers.
Definition GltfBuffers.h:17
Wrapper of Gltf file data.
Wrapper of Gltf Json Images.
Definition GltfImages.h:21
static bool Load(const std::string &fileName, GltfCollection *collection)
Load a gltf file to GltfCollection.
static bool LoadPack(GltfPack *pack, const GltfMeshes::Primitive &primitive, GltfAccessors *accessors, GltfBuffers *buffers, GltfBufferViews *bufferViews)
Load a gltf mesh to GltfPack.
static std::shared_ptr< Material > LoadMaterial(const GltfMaterials::Item &material, GltfImages *images)
Load a Material from Gltf file material component.
Loader of load gltf file or items.
Definition GltfLoader.h:23
Wrapper of Gltf Json Materials.
Wrapper of Gltf Json Meshes.
Definition GltfMeshes.h:17
GltfPack Class. This class defines gltf type meshPack.
Definition GltfPack.h:19
Material Class. This class contains a branch of parameter and shader, also descriptor.
Definition Material.h:62
Accessors Item data.
BufferViews Item data.
Buffers Item data.
Definition GltfBuffers.h:24
Materials Item data.
Primitive Item data.
Definition GltfMeshes.h:24