CSEngine
Loading...
Searching...
No Matches
DAELoader.cpp
1#include "DAELoader.h"
2#include "../../MoreString.h"
3#include "DAEUtil/DAEConvertSGameObject.h"
4#include "../../../Object/SGameObjectFromSPrefab.h"
5#include <iostream>
6#include "../../../Component/DrawableSkinnedMeshComponent.h"
7#include "../../../Component/RenderComponent.h"
8#include "../../Render/STexture.h"
9#include "../../Render/SMaterial.h"
10#include "../../../Manager/EngineCore.h"
11
12using namespace CSE;
13
14const mat4 CORRECTION = /*mat4::RotateX(90)*/ mat4::Identity();
15
16DAELoader::DAELoader(const char* path, LOAD_TYPE type, bool isLoad) {
17 if (type == NOTHING) return;
18
19 if (isLoad) Load(path, type);
20}
21
22DAELoader::~DAELoader() {
23 Exterminate();
24}
25
26void DAELoader::Load(const char* path, LOAD_TYPE type) {
27 {
28 std::string path_str = path;
29 std::size_t index = path_str.rfind('/');
30 if (index == std::string::npos) {
31 index = path_str.rfind('\\');
32 }
33 std::size_t name_index = path_str.rfind('.');
34
35 m_name = path_str.substr(index + 1, name_index - index - 1);
36 }
37
38 m_root = XFILE(path).getRoot();
39 XNode collada = m_root->getChild("COLLADA");
40
41 if (type == LOAD_TYPE::MESH || type == LOAD_TYPE::ALL || type == LOAD_TYPE::AUTO) {
42 try {
43 bool safe_result;
44 if(collada.hasChild("library_controllers") && collada.hasChild("library_visual_scenes")) {
45 safe_result = LoadSkin(collada.getChild("library_controllers"));
46 safe_result &= LoadSkeleton(collada.getChild("library_visual_scenes"));
47 }
48 else
49 safe_result = false;
50 m_isSkinning = safe_result;
51 } catch (int error) {
52 std::cout << "passing skinning...\n";
53 m_isSkinning = false;
54 }
55
56 try {
57 if(collada.hasChild("library_images"))
58 LoadTexturePath(collada.getChild("library_images"));
59 else
60 std::cout << "passing texture...\n";
61 } catch (int error) {
62 std::cout << "passing texture...\n";
63 }
64
65 try {
66 const auto& geometryData = collada.getChild("library_geometries").children;
67 m_meshList.reserve(geometryData.size());
68
69 for (const auto& geometry : geometryData) {
70 auto meshData = new DAEMeshData();
71 meshData->meshName = geometry.getAttribute("id").value;
72 LoadGeometry(geometry, meshData);
73 m_meshList.push_back(meshData);
74 }
75 } catch (int error) {
76 std::cout << "passing geometry...\n";
77 }
78 }
79 if (type == ANIMATION || type == ALL || type == AUTO) {
80 try {
81 bool safe_exception;
82 m_animationLoader = new DAEAnimationLoader();
83 safe_exception = m_animationLoader->Load(path, m_name);
84#ifdef __EMSCRIPTEN__
85 if(!safe_exception) {
86 SAFE_DELETE(m_animationLoader);
87 }
88#endif
89 } catch (int error) {
90 SAFE_DELETE(m_animationLoader);
91 std::cout << "passing Animation...\n";
92 }
93 }
94// LoadTexture(texture_path);
95}
96
97
98void DAELoader::LoadTexture(const AssetMgr::AssetReference* asset) {
99 if (asset == nullptr) return;
100
101 auto* texture = SResource::Create<STexture>(asset);
102 m_texture_name = texture->GetName();
103}
104
105void DAELoader::Exterminate() {
106 SAFE_DELETE(m_root);
107 for (auto mesh : m_meshList) {
108 SAFE_DELETE(mesh);
109 }
110 m_meshList.clear();
111
112 SAFE_DELETE(m_skinningData);
113 SAFE_DELETE(m_animationLoader);
114// m_skeletonData->Destroy();
115}
116
117bool DAELoader::LoadSkin(const XNode& root_s) {
118#ifdef __EMSCRIPTEN__
119 if(!root_s.hasChild("controller")) return false;
120#endif
121 XNode skinningData = root_s.getChild("controller").getChild("skin");
122
123 std::vector<std::string> jointsList = loadJointsList(skinningData);
124 std::vector<float> weights = loadWeights(skinningData);
125 const XNode& weightsDataNode = skinningData.getChild("vertex_weights");
126 std::vector<int> effectorJointCounts = getEffectiveJointsCounts(weightsDataNode);
127 std::vector<VertexSkinData*> vertexWeights = getSkinData(weightsDataNode, effectorJointCounts, weights);
128
129 SAFE_DELETE(m_skinningData);
130 m_skinningData = new SkinningData();
131 m_skinningData->set_jointOrder(jointsList);
132 m_skinningData->set_verticesSkinData(vertexWeights);
133 return true;
134}
135
136bool DAELoader::LoadSkeleton(const XNode& root_s) {
137#ifdef __EMSCRIPTEN__
138 if(!root_s.hasChild("visual_scene")) return false;
139 if(!root_s.getChild("visual_scene").hasNodeByAttribute("node", "id", "Armature")) return false;
140#endif
141 XNode armatureData = root_s.getChild("visual_scene").getNodeByAttribute("node", "id", "Armature");
142
143 const XNode& headNode = armatureData.getChild("node");
144 Joint* headJoint = loadJointData(headNode, true);
145
146
147 //SAFE_DELETE(m_skeletonData);
148 if (m_skeletonData == nullptr)
149 m_skeletonData = new Skeleton(m_jointSize, headJoint);
150 else
151 m_skeletonData->SetJoint(m_jointSize, headJoint);
152
153 return true;
154}
155
156bool DAELoader::LoadGeometry(const XNode& root_g, DAEMeshData* meshData) {
157#ifdef __EMSCRIPTEN__
158 if(!root_g.hasChild("mesh")) return false;
159#endif
160 const XNode& root_m = root_g.getChild("mesh");
161 std::vector<VertexSkinData*> vertexSkinData;
162 if (m_isSkinning) {
163 vertexSkinData =
164 m_skinningData == nullptr ? std::vector<VertexSkinData*>() : m_skinningData->get_verticesSkinData();
165 }
166
167 //RAW data
168 ReadPositions(root_m, vertexSkinData, meshData);
169
170
171 std::string normalsId;
172 std::string texCoordsId;
173
174 try {
175#ifdef __EMSCRIPTEN__
176 if(!root_m.hasChild("polylist")) return false;
177#endif
178 const XNode& polylist = root_m.getChild("polylist");
179
180 normalsId = polylist.getNodeByAttribute("input", "semantic", "NORMAL")
181 .getAttribute("source").value.substr(1);
182 const XNode& childWithAttribute = polylist.getNodeByAttribute("input", "semantic", "TEXCOORD");
183 texCoordsId = childWithAttribute.getAttribute("source").value.substr(1);
184 m_polygonType = POLYGON_TYPE::POLYLIST;
185 }
186 catch (int error) {
187 try {
188 const XNode& triangles = root_m.getChild("triangles");
189
190 const XNode& normals = triangles.getNodeByAttribute("input", "semantic", "NORMAL");
191 normalsId = normals.getAttribute("source").value.substr(1);
192 const XNode& childWithAttribute = triangles.getNodeByAttribute("input", "semantic", "TEXCOORD");
193 texCoordsId = childWithAttribute.getAttribute("source").value.substr(1);
194 m_polygonType = POLYGON_TYPE::TRIANGLES;
195 }
196 catch (int error) {}
197 }
198
199 ReadNormals(root_m, normalsId, meshData);
200 ReadUVs(root_m, texCoordsId, meshData);
201 AssembleVertices(root_m, meshData);
202 removeUnusedVertices(meshData);
203 ConvertDataToVectors(meshData);
204
205 return true;
206}
207
208//===================================================================
209// GeometryLoader Functions
210//===================================================================
211
212void DAELoader::ReadPositions(const XNode& data, std::vector<VertexSkinData*> vertexWeight, DAEMeshData* meshData) const {
213 std::string positionID = data.getChild("vertices").getChild("input").getAttribute("source").value.substr(1);
214 XNode positionData = data.getNodeByAttribute("source", "id", positionID.c_str()).getChild("float_array");
215 int vertsSize = std::stoi(positionData.getAttribute("count").value);
216 std::vector<float> vertices = positionData.value.toFloatVector();
217
218 for (int i = 0; i < vertsSize / 3; ++i) {
219 float x = vertices[i * 3];
220 float y = vertices[i * 3 + 1];
221 float z = vertices[i * 3 + 2];
222
223 // vec4 position = vec4{ x, y, z, 1 };
224 mat4 transform = mat4::Translate(x, y, z) * CORRECTION;
225 meshData->vertices.push_back(
226 new Vertex(meshData->vertices.size(), vec3{ transform.w.x, transform.w.y, transform.w.z },
227 m_isSkinning ? vertexWeight.at(meshData->vertices.size()) : nullptr));
228 }
229}
230
231void DAELoader::ReadNormals(const XNode& data, const std::string& normalsId, DAEMeshData* meshData) {
232 XNode normalsData = data.getNodeByAttribute("source", "id", normalsId.c_str()).getChild("float_array");
233 int normalsSize = std::stoi(normalsData.getAttribute("count").value);
234 std::vector<float> normals = normalsData.value.toFloatVector();
235
236 for (int i = 0; i < normalsSize / 3; i++) {
237 float x = normals[i * 3];
238 float y = normals[i * 3 + 1];
239 float z = normals[i * 3 + 2];
240
241 // vec4 normal = vec4{ x, y, z, 0 };
242 mat4 transform = mat4::Translate(x, y, z) * CORRECTION;
243 // std::cout << "{ " << x << ", " << y << ", " << z << " }, ";
244 // Matrix4f.transform(CORRECTION, normal, normal);
245 meshData->normals.emplace_back( transform.w.x, transform.w.y, transform.w.z );
246 }
247 // std::cout << "normal size : " << normalsSize << "\nnormal real size : " << m_normals.size() << '\n';
248}
249
250void DAELoader::ReadUVs(const XNode& data, const std::string& texCoordsId, DAEMeshData* meshData) {
251 XNode texData = data.getNodeByAttribute("source", "id", texCoordsId.c_str()).getChild("float_array");
252 int uvSize = std::stoi(texData.getAttribute("count").value);
253 auto uvs = texData.value.toFloatVector();
254
255 for (int i = 0; i < uvSize / 2; i++) {
256 float s = uvs[i * 2];
257 float t = uvs[i * 2 + 1];
258
259 meshData->texUVs.emplace_back( s, t );
260 }
261 // std::cout << "normal size : " << normalsSize << "\nnormal real size : " << m_normals.size() << '\n';
262}
263
264void DAELoader::AssembleVertices(const XNode& data, DAEMeshData* meshData) {
265 XNode poly = data.getChild(m_polygonType == POLYLIST ? "polylist" : "triangles");
266 int typeCount = 0;
267
268 for (const auto& child : poly.children) {
269 if (child.name == "input") {
270 int offset = std::stoi(child.getAttribute("offset").value) + 1;
271 if (offset > typeCount) {
272 typeCount = offset;
273 }
274 }
275 }
276
277 std::vector<int> indexData = poly.getChild("p").value.toIntegerVector();
278 int texcoordOffset = -1;
279 try {
280 const XNode& texSemantic = poly.getNodeByAttribute("input", "semantic", "TEXCOORD");
281 texcoordOffset = std::stoi(texSemantic.getAttribute("offset").value);
282 }
283 catch (int error) {
284 texcoordOffset = -1;
285 }
286
287 // std::cout << "\n\ntypeCount : " << typeCount << '\n';
288
289 for (int i = 0; i < indexData.size() / typeCount; i++) {
290 int positionIndex = indexData[i * typeCount];
291 int normalIndex = indexData[i * typeCount + 1];
292 int texCoordIndex = -1;
293 if (texcoordOffset != -1) {
294 texCoordIndex = indexData[i * typeCount + texcoordOffset];
295 }
296 processVertex(positionIndex, normalIndex, texCoordIndex, meshData);
297 }
298}
299
300Vertex* DAELoader::processVertex(int posIndex, int normIndex, int texIndex, DAEMeshData* meshData) {
301 Vertex* currentVertex = meshData->vertices.at(posIndex);
302 if (!currentVertex->isSet()) {
303 currentVertex->setTextureIndex(texIndex);
304 currentVertex->setNormalIndex(normIndex);
305 meshData->indices.push_back(posIndex);
306 // std::cout << "index = " << m_indices[m_indices.size() - 1] << " (processVertex)\n";
307 return currentVertex;
308 } else {
309 return dealWithAlreadyProcessedVertex(currentVertex, texIndex, normIndex, meshData);
310 }
311}
312
313Vertex* DAELoader::dealWithAlreadyProcessedVertex(Vertex* previousVertex, int newTextureIndex, int newNormalIndex,
314 DAEMeshData* meshData) {
315 if (previousVertex->hasSameTextureAndNormal(newTextureIndex, newNormalIndex)) {
316 meshData->indices.push_back(previousVertex->getIndex());
317 // std::cout << "index = " << m_indices[m_indices.size() - 1] << " (hasSameTextureAndNormal)\n";
318 return previousVertex;
319 } else {
320 Vertex* anotherVertex = previousVertex->getDuplicateVertex();
321 if (anotherVertex != nullptr) {
322 return dealWithAlreadyProcessedVertex(anotherVertex, newTextureIndex, newNormalIndex, meshData);
323 } else {
324 auto* duplicateVertex = new Vertex(meshData->vertices.size(),
325 previousVertex->getPosition(), previousVertex->getWeightsData());
326 duplicateVertex->setTextureIndex(newTextureIndex);
327 duplicateVertex->setNormalIndex(newNormalIndex);
328 previousVertex->setDuplicateVertex(duplicateVertex);
329 meshData->vertices.push_back(duplicateVertex);
330 meshData->indices.push_back(duplicateVertex->getIndex());
331 // std::cout << "index = " << m_indices[m_indices.size() - 1] << " (else)\n";
332 return duplicateVertex;
333 }
334 }
335}
336
337void DAELoader::removeUnusedVertices(DAEMeshData* meshData) {
338 for (const auto& vertex : meshData->vertices) {
339 vertex->averageTangents();
340 if (!vertex->isSet()) {
341 vertex->setTextureIndex(0);
342 vertex->setNormalIndex(0);
343 }
344 }
345}
346
347//===================================================================
348// SkinLoader Functions
349//===================================================================
350
351std::vector<std::string> DAELoader::loadJointsList(const XNode& skinningData) {
352 const XNode& inputNode = skinningData.getChild("vertex_weights");
353 std::string jointDataId = inputNode.getNodeByAttribute("input", "semantic", "JOINT").getAttribute(
354 "source").value.substr(1);
355 XNode jointsNode = skinningData.getNodeByAttribute("source", "id", jointDataId.c_str()).getChild("Name_array");
356
357 std::vector<std::string> jointsList = jointsNode.value.toStringVector();
358
359 return jointsList;
360}
361
362std::vector<float> DAELoader::loadWeights(const XNode& skinningData) {
363 const XNode& inputNode = skinningData.getChild("vertex_weights");
364 std::string weightsDataId = inputNode.getNodeByAttribute("input", "semantic", "WEIGHT").getAttribute(
365 "source").value.substr(1);
366 XNode weightsNode = skinningData.getNodeByAttribute("source", "id", weightsDataId.c_str()).getChild("float_array");
367 std::vector<float> weights = weightsNode.value.toFloatVector();
368
369 return weights;
370}
371
372std::vector<int> DAELoader::getEffectiveJointsCounts(const XNode& node) {
373 if(m_polygonType == POLYLIST) {
374 return node.getChild("vcount").value.toIntegerVector();
375 }
376
377 // TODO: Triangle 형식일 때의 Joint 갯수를 작성해야 함
378 return {};
379}
380
381std::vector<VertexSkinData*>
382DAELoader::getSkinData(const XNode& weightsDataNode, const std::vector<int>& counts, std::vector<float> weights) const {
383 auto rawData = weightsDataNode.getChild("v").value.toIntegerVector();
384 auto weightsCount = std::stoi(weightsDataNode.getAttribute("count").value);
385 std::vector<VertexSkinData*> skinningData;
386 int pointer = 0;
387 for (int index = 0; index < weightsCount; ++index) {
388 auto* skinData = new VertexSkinData();
389 short count = (m_polygonType == POLYLIST) ? counts[index] : static_cast<short>(m_polygonType);
390 for (short i = 0; i < count; ++i) {
391 int jointId = rawData[pointer++];
392 int weightId = rawData[pointer++];
393 skinData->addJointEffect(jointId, weights[weightId]);
394 }
395 skinData->limitJointNumber(m_maxWeight);
396 skinningData.push_back(skinData);
397 }
398 return skinningData;
399}
400
401//===================================================================
402// SkeletonLoader Functions
403//===================================================================
404
405Joint* DAELoader::extractMainJointData(const XNode& jointNode, bool isRoot) {
406 std::string nameId = jointNode.getAttribute("id").value;
407 int index = -1;
408 auto jointOrders = m_skinningData->get_jointOrder();
409 for (int i = 0; i < jointOrders.size(); ++i) {
410 if (trim(jointOrders[i]) == nameId) {
411 index = i;
412 break;
413 }
414 }
415
416 if (index < 0)
417 return nullptr;
418
419 std::vector<float> matrixData = jointNode.getChild("matrix").value.toFloatVector();
420 mat4 matrix = mat4(&matrixData[0]);
421 matrix = matrix.Transposed();
422 if (isRoot) {
423 //because in Blender z is up, but in our game y is up.
424 matrix *= CORRECTION;
425 }
426 m_jointSize++;
427 return new Joint(index, nameId, matrix);
428}
429
430Joint* DAELoader::loadJointData(const XNode& jointNode, bool isRoot) {
431 Joint* joint = extractMainJointData(jointNode, isRoot);
432
433 try {
434 for (const XNode& childNode : jointNode.children) {
435 if (childNode.name == "node") {
436 joint->addChild(loadJointData(childNode, false));
437 }
438 }
439 } catch (int error) {}
440
441 return joint;
442}
443
444void DAELoader::LoadTexturePath(const XNode& imageNode) {
445#ifdef __EMSCRIPTEN__
446 if(!imageNode.hasChild("image")) return;
447#endif
448 std::string path = imageNode.getChild("image").getChild("init_from").value;
449 path = trim(path);
450 auto asset = CORE->GetCore(ResMgr)->GetAssetReference(path);
451 if (asset == nullptr) return;
452
453 LoadTexture(asset);
454}
455
456void DAELoader::ConvertDataToVectors(DAEMeshData* meshData) const {
457 std::vector<float> vertices;
458 std::vector<float> normals;
459 std::vector<float> texUVs;
460 std::vector<short> jointIDs;
461 std::vector<float> weights;
462
463 {
464 int size = meshData->vertices.size();
465 vertices.resize(size * 3);
466 normals.resize(size * 3);
467 texUVs.resize(size * 2);
468 if (m_isSkinning) {
469 jointIDs.resize(size * 3);
470 weights.resize(size * 3);
471 }
472 }
473
474 float furthestPoint = 0;
475 int vertices_size = meshData->vertices.size();
476 for (int i = 0; i < vertices_size; ++i) {
477 Vertex& currentVertex = *meshData->vertices[i];
478 if (currentVertex.getLength() > furthestPoint) {
479 furthestPoint = currentVertex.getLength();
480 }
481 vec3 position = currentVertex.getPosition();
482 // vec2 textureCoord = textures.get(currentVertex.getTextureIndex());
483 vec2 textureCoord = meshData->texUVs.at(currentVertex.getTextureIndex());
484 vec3 normalVector = meshData->normals.at(currentVertex.getNormalIndex());
485 vertices[i * 3] = position.x;
486 vertices[i * 3 + 1] = position.y;
487 vertices[i * 3 + 2] = position.z;
488 texUVs[i * 2] = textureCoord.x;
489 texUVs[i * 2 + 1] = 1 - textureCoord.y;
490 normals[i * 3] = normalVector.x;
491 normals[i * 3 + 1] = normalVector.y;
492 normals[i * 3 + 2] = normalVector.z;
493
494 if (!m_isSkinning) continue;
495
496 VertexSkinData* weightsData = currentVertex.getWeightsData();
497 jointIDs[i * 3] = weightsData->getJointIDs()[0];
498 jointIDs[i * 3 + 1] = weightsData->getJointIDs()[1];
499 jointIDs[i * 3 + 2] = weightsData->getJointIDs()[2];
500 weights[i * 3] = weightsData->getWeights()[0];
501 weights[i * 3 + 1] = weightsData->getWeights()[1];
502 weights[i * 3 + 2] = weightsData->getWeights()[2];
503 }
504 AttachDataToObjSurface(meshData->vertices.size(), vertices, normals, texUVs, meshData->indices, jointIDs, weights,
505 meshData);
506}
507
508void
509DAELoader::AttachDataToObjSurface(int vertices_size, std::vector<float> vertices, std::vector<float> normals,
510 std::vector<float> texUVs, std::vector<int> indices, std::vector<short> jointIDs,
511 std::vector<float> weights, DAEMeshData* meshData) {
512 int sizeIndices = indices.size() / 3;
513 const auto meshSurface = meshData->meshSurface;
514 meshSurface->MakeVertices(vertices_size, &vertices[0], &normals[0], (texUVs.empty() ? nullptr : &texUVs[0]),
515 (weights.empty() ? nullptr : &weights[0]), (jointIDs.empty() ? nullptr : &jointIDs[0]));
516 meshSurface->MakeIndices(sizeIndices, &indices[0]);
517}
518
519SPrefab* DAELoader::GeneratePrefab(Animation* animation, SPrefab* prefab) {
520 if (prefab == nullptr)
521 prefab = new SPrefab();
522 auto* root = new SGameObjectFromSPrefab(m_name);
523 prefab->SetGameObject(root);
524
525 SGameObject* joint_root = nullptr;
526
527 if (m_isSkinning) {
528 joint_root = new SGameObjectFromSPrefab("Armature");
529 root->AddChild(joint_root);
530 DAEConvertSGameObject::CreateJoints(joint_root, m_skeletonData->getHeadJoint());
531 }
532
533 JointComponent* joint_root_component = m_isSkinning ? joint_root->GetChildren().front()->GetComponent<JointComponent>() : nullptr;
534 for (const auto& mesh : m_meshList) {
535 auto* mesh_root = new SGameObjectFromSPrefab(mesh->meshName);
536 root->AddChild(mesh_root);
537 DrawableStaticMeshComponent* mesh_component = nullptr;
538
539 if (m_isSkinning) {
540 mesh_component = mesh_root->CreateComponent<DrawableSkinnedMeshComponent>();
541 } else {
542 mesh_component = mesh_root->CreateComponent<DrawableStaticMeshComponent>();
543 }
544
545 mesh_component->SetMesh(*mesh->meshSurface);
546
547 if (m_isSkinning)
548 dynamic_cast<DrawableSkinnedMeshComponent*>(mesh_component)->SetRootJoint(
549 joint_root_component->GetGameObject(),
550 m_skeletonData->getJointCount());
551
552 auto renderComponent = mesh_root->CreateComponent<RenderComponent>();
553// mesh_root->GetComponent<RenderComponent>()->SetShaderHandle("PBR.shader");
554 }
555
556 if (m_isSkinning) {
557 SGameObject* animationObj = DAEConvertSGameObject::CreateAnimation(root, joint_root_component,
558 m_animationLoader->GetAnimation(),
559 m_name, animation);
560 }
561
562 return prefab;
563}
564
565SPrefab* DAELoader::GeneratePrefab(const char* path, Skeleton* skeleton, MeshSurface* mesh, Animation* animation,
566 SPrefab* prefab) {
567 auto* loader = new DAELoader(path, AUTO, false);
568 auto asset = CORE->GetCore(ResMgr)->GetAssetReference(path);
569 if (asset == nullptr) {
570 SAFE_DELETE(loader);
571 return nullptr;
572 }
573 std::string prefab_id = asset->id;
574
575 loader->m_resource_id = asset->id;
576 loader->m_skeletonData = skeleton;
577
578 if (loader->m_skeletonData == nullptr) {
579 loader->m_skeletonData = new Skeleton();
580 }
581
582 const auto& meshData = loader->m_meshList;
583 for (const auto& mesh : meshData) {
584 mesh->meshSurface->LinkResource(prefab_id + "." + mesh->meshName +"?mesh");
585 }
586 loader->m_skeletonData->LinkResource(prefab_id + "?skeleton");
587
588 loader->Load(path, AUTO);
589 prefab = loader->GeneratePrefab(animation, prefab);
590
591 SAFE_DELETE(loader);
592 return prefab;
593}
Definition XML.h:77
Definition XML.h:43