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 if (root_m.hasChild("polylist")) {
175 const XNode& polylist = root_m.getChild("polylist");
176
177 normalsId = polylist.getNodeByAttribute("input", "semantic", "NORMAL")
178 .getAttribute("source").value.substr(1);
179 const XNode& childWithAttribute = polylist.getNodeByAttribute("input", "semantic", "TEXCOORD");
180 texCoordsId = childWithAttribute.getAttribute("source").value.substr(1);
181 m_polygonType = POLYGON_TYPE::POLYLIST;
182 }
183 else if (root_m.hasChild("triangles")) {
184 const XNode& triangles = root_m.getChild("triangles");
185
186 const XNode& normals = triangles.getNodeByAttribute("input", "semantic", "NORMAL");
187 normalsId = normals.getAttribute("source").value.substr(1);
188 const XNode& childWithAttribute = triangles.getNodeByAttribute("input", "semantic", "TEXCOORD");
189 texCoordsId = childWithAttribute.getAttribute("source").value.substr(1);
190 m_polygonType = POLYGON_TYPE::TRIANGLES;
191 }
192
193 ReadNormals(root_m, normalsId, meshData);
194 ReadUVs(root_m, texCoordsId, meshData);
195 AssembleVertices(root_m, meshData);
196 removeUnusedVertices(meshData);
197 ConvertDataToVectors(meshData);
198
199 return true;
200}
201
202//===================================================================
203// GeometryLoader Functions
204//===================================================================
205
206void DAELoader::ReadPositions(const XNode& data, std::vector<VertexSkinData*> vertexWeight, DAEMeshData* meshData) const {
207 std::string positionID = data.getChild("vertices").getChild("input").getAttribute("source").value.substr(1);
208 XNode positionData = data.getNodeByAttribute("source", "id", positionID.c_str()).getChild("float_array");
209 int vertsSize = std::stoi(positionData.getAttribute("count").value);
210 std::vector<float> vertices = positionData.value.toFloatVector();
211
212 for (int i = 0; i < vertsSize / 3; ++i) {
213 float x = vertices[i * 3];
214 float y = vertices[i * 3 + 1];
215 float z = vertices[i * 3 + 2];
216
217 // vec4 position = vec4{ x, y, z, 1 };
218 mat4 transform = mat4::Translate(x, y, z) * CORRECTION;
219 meshData->vertices.push_back(
220 new Vertex(meshData->vertices.size(), vec3{ transform.w.x, transform.w.y, transform.w.z },
221 m_isSkinning ? vertexWeight.at(meshData->vertices.size()) : nullptr));
222 }
223}
224
225void DAELoader::ReadNormals(const XNode& data, const std::string& normalsId, DAEMeshData* meshData) {
226 XNode normalsData = data.getNodeByAttribute("source", "id", normalsId.c_str()).getChild("float_array");
227 int normalsSize = std::stoi(normalsData.getAttribute("count").value);
228 std::vector<float> normals = normalsData.value.toFloatVector();
229
230 for (int i = 0; i < normalsSize / 3; i++) {
231 float x = normals[i * 3];
232 float y = normals[i * 3 + 1];
233 float z = normals[i * 3 + 2];
234
235 // vec4 normal = vec4{ x, y, z, 0 };
236 mat4 transform = mat4::Translate(x, y, z) * CORRECTION;
237 // std::cout << "{ " << x << ", " << y << ", " << z << " }, ";
238 // Matrix4f.transform(CORRECTION, normal, normal);
239 meshData->normals.emplace_back( transform.w.x, transform.w.y, transform.w.z );
240 }
241 // std::cout << "normal size : " << normalsSize << "\nnormal real size : " << m_normals.size() << '\n';
242}
243
244void DAELoader::ReadUVs(const XNode& data, const std::string& texCoordsId, DAEMeshData* meshData) {
245 XNode texData = data.getNodeByAttribute("source", "id", texCoordsId.c_str()).getChild("float_array");
246 int uvSize = std::stoi(texData.getAttribute("count").value);
247 auto uvs = texData.value.toFloatVector();
248
249 for (int i = 0; i < uvSize / 2; i++) {
250 float s = uvs[i * 2];
251 float t = uvs[i * 2 + 1];
252
253 meshData->texUVs.emplace_back( s, t );
254 }
255 // std::cout << "normal size : " << normalsSize << "\nnormal real size : " << m_normals.size() << '\n';
256}
257
258void DAELoader::AssembleVertices(const XNode& data, DAEMeshData* meshData) {
259 XNode poly = data.getChild(m_polygonType == POLYLIST ? "polylist" : "triangles");
260 int typeCount = 0;
261
262 for (const auto& child : poly.children) {
263 if (child.name == "input") {
264 int offset = std::stoi(child.getAttribute("offset").value) + 1;
265 if (offset > typeCount) {
266 typeCount = offset;
267 }
268 }
269 }
270
271 std::vector<int> indexData = poly.getChild("p").value.toIntegerVector();
272 int texcoordOffset = -1;
273 try {
274 const XNode& texSemantic = poly.getNodeByAttribute("input", "semantic", "TEXCOORD");
275 texcoordOffset = std::stoi(texSemantic.getAttribute("offset").value);
276 }
277 catch (int error) {
278 texcoordOffset = -1;
279 }
280
281 // std::cout << "\n\ntypeCount : " << typeCount << '\n';
282
283 for (int i = 0; i < indexData.size() / typeCount; i++) {
284 int positionIndex = indexData[i * typeCount];
285 int normalIndex = indexData[i * typeCount + 1];
286 int texCoordIndex = -1;
287 if (texcoordOffset != -1) {
288 texCoordIndex = indexData[i * typeCount + texcoordOffset];
289 }
290 processVertex(positionIndex, normalIndex, texCoordIndex, meshData);
291 }
292}
293
294Vertex* DAELoader::processVertex(int posIndex, int normIndex, int texIndex, DAEMeshData* meshData) {
295 Vertex* currentVertex = meshData->vertices.at(posIndex);
296 if (!currentVertex->isSet()) {
297 currentVertex->setTextureIndex(texIndex);
298 currentVertex->setNormalIndex(normIndex);
299 meshData->indices.push_back(posIndex);
300 // std::cout << "index = " << m_indices[m_indices.size() - 1] << " (processVertex)\n";
301 return currentVertex;
302 } else {
303 return dealWithAlreadyProcessedVertex(currentVertex, texIndex, normIndex, meshData);
304 }
305}
306
307Vertex* DAELoader::dealWithAlreadyProcessedVertex(Vertex* previousVertex, int newTextureIndex, int newNormalIndex,
308 DAEMeshData* meshData) {
309 if (previousVertex->hasSameTextureAndNormal(newTextureIndex, newNormalIndex)) {
310 meshData->indices.push_back(previousVertex->getIndex());
311 // std::cout << "index = " << m_indices[m_indices.size() - 1] << " (hasSameTextureAndNormal)\n";
312 return previousVertex;
313 } else {
314 Vertex* anotherVertex = previousVertex->getDuplicateVertex();
315 if (anotherVertex != nullptr) {
316 return dealWithAlreadyProcessedVertex(anotherVertex, newTextureIndex, newNormalIndex, meshData);
317 } else {
318 auto* duplicateVertex = new Vertex(meshData->vertices.size(),
319 previousVertex->getPosition(), previousVertex->getWeightsData());
320 duplicateVertex->setTextureIndex(newTextureIndex);
321 duplicateVertex->setNormalIndex(newNormalIndex);
322 previousVertex->setDuplicateVertex(duplicateVertex);
323 meshData->vertices.push_back(duplicateVertex);
324 meshData->indices.push_back(duplicateVertex->getIndex());
325 // std::cout << "index = " << m_indices[m_indices.size() - 1] << " (else)\n";
326 return duplicateVertex;
327 }
328 }
329}
330
331void DAELoader::removeUnusedVertices(DAEMeshData* meshData) {
332 for (const auto& vertex : meshData->vertices) {
333 vertex->averageTangents();
334 if (!vertex->isSet()) {
335 vertex->setTextureIndex(0);
336 vertex->setNormalIndex(0);
337 }
338 }
339}
340
341//===================================================================
342// SkinLoader Functions
343//===================================================================
344
345std::vector<std::string> DAELoader::loadJointsList(const XNode& skinningData) {
346 const XNode& inputNode = skinningData.getChild("vertex_weights");
347 std::string jointDataId = inputNode.getNodeByAttribute("input", "semantic", "JOINT").getAttribute(
348 "source").value.substr(1);
349 XNode jointsNode = skinningData.getNodeByAttribute("source", "id", jointDataId.c_str()).getChild("Name_array");
350
351 std::vector<std::string> jointsList = jointsNode.value.toStringVector();
352
353 return jointsList;
354}
355
356std::vector<float> DAELoader::loadWeights(const XNode& skinningData) {
357 const XNode& inputNode = skinningData.getChild("vertex_weights");
358 std::string weightsDataId = inputNode.getNodeByAttribute("input", "semantic", "WEIGHT").getAttribute(
359 "source").value.substr(1);
360 XNode weightsNode = skinningData.getNodeByAttribute("source", "id", weightsDataId.c_str()).getChild("float_array");
361 std::vector<float> weights = weightsNode.value.toFloatVector();
362
363 return weights;
364}
365
366std::vector<int> DAELoader::getEffectiveJointsCounts(const XNode& node) {
367 if(m_polygonType == POLYLIST) {
368 return node.getChild("vcount").value.toIntegerVector();
369 }
370
371 // TODO: Triangle 형식일 때의 Joint 갯수를 작성해야 함
372 return {};
373}
374
375std::vector<VertexSkinData*>
376DAELoader::getSkinData(const XNode& weightsDataNode, const std::vector<int>& counts, std::vector<float> weights) const {
377 auto rawData = weightsDataNode.getChild("v").value.toIntegerVector();
378 auto weightsCount = std::stoi(weightsDataNode.getAttribute("count").value);
379 std::vector<VertexSkinData*> skinningData;
380 int pointer = 0;
381 for (int index = 0; index < weightsCount; ++index) {
382 auto* skinData = new VertexSkinData();
383 short count = (m_polygonType == POLYLIST) ? counts[index] : static_cast<short>(m_polygonType);
384 for (short i = 0; i < count; ++i) {
385 int jointId = rawData[pointer++];
386 int weightId = rawData[pointer++];
387 skinData->addJointEffect(jointId, weights[weightId]);
388 }
389 skinData->limitJointNumber(m_maxWeight);
390 skinningData.push_back(skinData);
391 }
392 return skinningData;
393}
394
395//===================================================================
396// SkeletonLoader Functions
397//===================================================================
398
399Joint* DAELoader::extractMainJointData(const XNode& jointNode, bool isRoot) {
400 std::string nameId = jointNode.getAttribute("id").value;
401 int index = -1;
402 auto jointOrders = m_skinningData->get_jointOrder();
403 for (int i = 0; i < jointOrders.size(); ++i) {
404 if (trim(jointOrders[i]) == nameId) {
405 index = i;
406 break;
407 }
408 }
409
410 if (index < 0)
411 return nullptr;
412
413 std::vector<float> matrixData = jointNode.getChild("matrix").value.toFloatVector();
414 mat4 matrix = mat4(&matrixData[0]);
415 matrix = matrix.Transposed();
416 if (isRoot) {
417 //because in Blender z is up, but in our game y is up.
418 matrix *= CORRECTION;
419 }
420 m_jointSize++;
421 return new Joint(index, nameId, matrix);
422}
423
424Joint* DAELoader::loadJointData(const XNode& jointNode, bool isRoot) {
425 Joint* joint = extractMainJointData(jointNode, isRoot);
426
427 try {
428 for (const XNode& childNode : jointNode.children) {
429 if (childNode.name == "node") {
430 joint->addChild(loadJointData(childNode, false));
431 }
432 }
433 } catch (int error) {}
434
435 return joint;
436}
437
438void DAELoader::LoadTexturePath(const XNode& imageNode) {
439#ifdef __EMSCRIPTEN__
440 if(!imageNode.hasChild("image")) return;
441#endif
442 std::string path = imageNode.getChild("image").getChild("init_from").value;
443 path = trim(path);
444 auto asset = CORE->GetCore(ResMgr)->GetAssetReference(path);
445 if (asset == nullptr) return;
446
447 LoadTexture(asset);
448}
449
450void DAELoader::ConvertDataToVectors(DAEMeshData* meshData) const {
451 std::vector<float> vertices;
452 std::vector<float> normals;
453 std::vector<float> texUVs;
454 std::vector<short> jointIDs;
455 std::vector<float> weights;
456
457 {
458 int size = meshData->vertices.size();
459 vertices.resize(size * 3);
460 normals.resize(size * 3);
461 texUVs.resize(size * 2);
462 if (m_isSkinning) {
463 jointIDs.resize(size * 3);
464 weights.resize(size * 3);
465 }
466 }
467
468 float furthestPoint = 0;
469 int vertices_size = meshData->vertices.size();
470 for (int i = 0; i < vertices_size; ++i) {
471 Vertex& currentVertex = *meshData->vertices[i];
472 if (currentVertex.getLength() > furthestPoint) {
473 furthestPoint = currentVertex.getLength();
474 }
475 vec3 position = currentVertex.getPosition();
476 // vec2 textureCoord = textures.get(currentVertex.getTextureIndex());
477 vec2 textureCoord = meshData->texUVs.at(currentVertex.getTextureIndex());
478 vec3 normalVector = meshData->normals.at(currentVertex.getNormalIndex());
479 vertices[i * 3] = position.x;
480 vertices[i * 3 + 1] = position.y;
481 vertices[i * 3 + 2] = position.z;
482 texUVs[i * 2] = textureCoord.x;
483 texUVs[i * 2 + 1] = 1 - textureCoord.y;
484 normals[i * 3] = normalVector.x;
485 normals[i * 3 + 1] = normalVector.y;
486 normals[i * 3 + 2] = normalVector.z;
487
488 if (!m_isSkinning) continue;
489
490 VertexSkinData* weightsData = currentVertex.getWeightsData();
491 jointIDs[i * 3] = weightsData->getJointIDs()[0];
492 jointIDs[i * 3 + 1] = weightsData->getJointIDs()[1];
493 jointIDs[i * 3 + 2] = weightsData->getJointIDs()[2];
494 weights[i * 3] = weightsData->getWeights()[0];
495 weights[i * 3 + 1] = weightsData->getWeights()[1];
496 weights[i * 3 + 2] = weightsData->getWeights()[2];
497 }
498 AttachDataToObjSurface(meshData->vertices.size(), vertices, normals, texUVs, meshData->indices, jointIDs, weights,
499 meshData);
500}
501
502void
503DAELoader::AttachDataToObjSurface(int vertices_size, std::vector<float> vertices, std::vector<float> normals,
504 std::vector<float> texUVs, std::vector<int> indices, std::vector<short> jointIDs,
505 std::vector<float> weights, DAEMeshData* meshData) {
506 int sizeIndices = indices.size() / 3;
507 const auto meshSurface = meshData->meshSurface;
508 meshSurface->MakeVertices(vertices_size, &vertices[0], &normals[0], (texUVs.empty() ? nullptr : &texUVs[0]),
509 (weights.empty() ? nullptr : &weights[0]), (jointIDs.empty() ? nullptr : &jointIDs[0]));
510 meshSurface->MakeIndices(sizeIndices, &indices[0]);
511}
512
513SPrefab* DAELoader::GeneratePrefab(Animation* animation, SPrefab* prefab) {
514 if (prefab == nullptr)
515 prefab = new SPrefab();
516 auto* root = new SGameObjectFromSPrefab(m_name);
517 prefab->SetGameObject(root);
518
519 SGameObject* joint_root = nullptr;
520
521 if (m_isSkinning) {
522 joint_root = new SGameObjectFromSPrefab("Armature");
523 root->AddChild(joint_root);
524 DAEConvertSGameObject::CreateJoints(joint_root, m_skeletonData->getHeadJoint());
525 }
526
527 JointComponent* joint_root_component = m_isSkinning ? joint_root->GetChildren().front()->GetComponent<JointComponent>() : nullptr;
528 for (const auto& mesh : m_meshList) {
529 auto* mesh_root = new SGameObjectFromSPrefab(mesh->meshName);
530 root->AddChild(mesh_root);
531 DrawableStaticMeshComponent* mesh_component = nullptr;
532
533 if (m_isSkinning) {
534 mesh_component = mesh_root->CreateComponent<DrawableSkinnedMeshComponent>();
535 } else {
536 mesh_component = mesh_root->CreateComponent<DrawableStaticMeshComponent>();
537 }
538
539 mesh_component->SetMesh(*mesh->meshSurface);
540
541 if (m_isSkinning)
542 dynamic_cast<DrawableSkinnedMeshComponent*>(mesh_component)->SetRootJoint(
543 joint_root_component->GetGameObject(),
544 m_skeletonData->getJointCount());
545
546 auto renderComponent = mesh_root->CreateComponent<RenderComponent>();
547// mesh_root->GetComponent<RenderComponent>()->SetShaderHandle("PBR.shader");
548 }
549
550 if (m_isSkinning) {
551 SGameObject* animationObj = DAEConvertSGameObject::CreateAnimation(root, joint_root_component,
552 m_animationLoader->GetAnimation(),
553 m_name, animation);
554 }
555
556 return prefab;
557}
558
559SPrefab* DAELoader::GeneratePrefab(const char* path, Skeleton* skeleton, MeshSurface* mesh, Animation* animation,
560 SPrefab* prefab) {
561 auto* loader = new DAELoader(path, AUTO, false);
562 auto asset = CORE->GetCore(ResMgr)->GetAssetReference(path);
563 if (asset == nullptr) {
564 SAFE_DELETE(loader);
565 return nullptr;
566 }
567 std::string prefab_id = asset->id;
568
569 loader->m_resource_id = asset->id;
570 loader->m_skeletonData = skeleton;
571
572 if (loader->m_skeletonData == nullptr) {
573 loader->m_skeletonData = new Skeleton();
574 }
575
576 const auto& meshData = loader->m_meshList;
577 for (const auto& mesh : meshData) {
578 mesh->meshSurface->LinkResource(prefab_id + "." + mesh->meshName +"?mesh");
579 }
580 loader->m_skeletonData->LinkResource(prefab_id + "?skeleton");
581
582 loader->Load(path, AUTO);
583 prefab = loader->GeneratePrefab(animation, prefab);
584
585 SAFE_DELETE(loader);
586 return prefab;
587}
Definition XML.h:77
Definition XML.h:43