2#include "../../MoreString.h"
3#include "DAEUtil/DAEConvertSGameObject.h"
4#include "../../../Object/SGameObjectFromSPrefab.h"
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"
14const mat4 CORRECTION = mat4::Identity();
16DAELoader::DAELoader(
const char* path, LOAD_TYPE type,
bool isLoad) {
17 if (type == NOTHING)
return;
19 if (isLoad) Load(path, type);
22DAELoader::~DAELoader() {
26void DAELoader::Load(
const char* path, LOAD_TYPE type) {
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(
'\\');
33 std::size_t name_index = path_str.rfind(
'.');
35 m_name = path_str.substr(index + 1, name_index - index - 1);
38 m_root =
XFILE(path).getRoot();
39 XNode collada = m_root->getChild(
"COLLADA");
41 if (type == LOAD_TYPE::MESH || type == LOAD_TYPE::ALL || type == LOAD_TYPE::AUTO) {
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"));
50 m_isSkinning = safe_result;
52 std::cout <<
"passing skinning...\n";
57 if(collada.hasChild(
"library_images"))
58 LoadTexturePath(collada.getChild(
"library_images"));
60 std::cout <<
"passing texture...\n";
62 std::cout <<
"passing texture...\n";
66 const auto& geometryData = collada.getChild(
"library_geometries").children;
67 m_meshList.reserve(geometryData.size());
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);
76 std::cout <<
"passing geometry...\n";
79 if (type == ANIMATION || type == ALL || type == AUTO) {
83 safe_exception = m_animationLoader->Load(path, m_name);
86 SAFE_DELETE(m_animationLoader);
90 SAFE_DELETE(m_animationLoader);
91 std::cout <<
"passing Animation...\n";
99 if (asset ==
nullptr)
return;
101 auto* texture = SResource::Create<STexture>(asset);
102 m_texture_name = texture->GetName();
105void DAELoader::Exterminate() {
107 for (
auto mesh : m_meshList) {
112 SAFE_DELETE(m_skinningData);
113 SAFE_DELETE(m_animationLoader);
117bool DAELoader::LoadSkin(
const XNode& root_s) {
119 if(!root_s.hasChild(
"controller"))
return false;
121 XNode skinningData = root_s.getChild(
"controller").getChild(
"skin");
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);
129 SAFE_DELETE(m_skinningData);
131 m_skinningData->set_jointOrder(jointsList);
132 m_skinningData->set_verticesSkinData(vertexWeights);
136bool DAELoader::LoadSkeleton(
const XNode& root_s) {
138 if(!root_s.hasChild(
"visual_scene"))
return false;
139 if(!root_s.getChild(
"visual_scene").hasNodeByAttribute(
"node",
"id",
"Armature"))
return false;
141 XNode armatureData = root_s.getChild(
"visual_scene").getNodeByAttribute(
"node",
"id",
"Armature");
143 const XNode& headNode = armatureData.getChild(
"node");
144 Joint* headJoint = loadJointData(headNode,
true);
148 if (m_skeletonData ==
nullptr)
149 m_skeletonData =
new Skeleton(m_jointSize, headJoint);
151 m_skeletonData->SetJoint(m_jointSize, headJoint);
156bool DAELoader::LoadGeometry(
const XNode& root_g, DAEMeshData* meshData) {
158 if(!root_g.hasChild(
"mesh"))
return false;
160 const XNode& root_m = root_g.getChild(
"mesh");
161 std::vector<VertexSkinData*> vertexSkinData;
164 m_skinningData ==
nullptr ? std::vector<VertexSkinData*>() : m_skinningData->get_verticesSkinData();
168 ReadPositions(root_m, vertexSkinData, meshData);
171 std::string normalsId;
172 std::string texCoordsId;
174 if (root_m.hasChild(
"polylist")) {
175 const XNode& polylist = root_m.getChild(
"polylist");
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;
183 else if (root_m.hasChild(
"triangles")) {
184 const XNode& triangles = root_m.getChild(
"triangles");
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;
193 ReadNormals(root_m, normalsId, meshData);
194 ReadUVs(root_m, texCoordsId, meshData);
195 AssembleVertices(root_m, meshData);
196 removeUnusedVertices(meshData);
197 ConvertDataToVectors(meshData);
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();
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];
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));
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();
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];
236 mat4 transform = mat4::Translate(x, y, z) * CORRECTION;
239 meshData->normals.emplace_back( transform.w.x, transform.w.y, transform.w.z );
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();
249 for (
int i = 0; i < uvSize / 2; i++) {
250 float s = uvs[i * 2];
251 float t = uvs[i * 2 + 1];
253 meshData->texUVs.emplace_back( s, t );
258void DAELoader::AssembleVertices(
const XNode& data, DAEMeshData* meshData) {
259 XNode poly = data.getChild(m_polygonType == POLYLIST ?
"polylist" :
"triangles");
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) {
271 std::vector<int> indexData = poly.getChild(
"p").value.toIntegerVector();
272 int texcoordOffset = -1;
274 const XNode& texSemantic = poly.getNodeByAttribute(
"input",
"semantic",
"TEXCOORD");
275 texcoordOffset = std::stoi(texSemantic.getAttribute(
"offset").value);
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];
290 processVertex(positionIndex, normalIndex, texCoordIndex, meshData);
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);
301 return currentVertex;
303 return dealWithAlreadyProcessedVertex(currentVertex, texIndex, normIndex, meshData);
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());
312 return previousVertex;
314 Vertex* anotherVertex = previousVertex->getDuplicateVertex();
315 if (anotherVertex !=
nullptr) {
316 return dealWithAlreadyProcessedVertex(anotherVertex, newTextureIndex, newNormalIndex, meshData);
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());
326 return duplicateVertex;
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);
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");
351 std::vector<std::string> jointsList = jointsNode.value.toStringVector();
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();
366std::vector<int> DAELoader::getEffectiveJointsCounts(
const XNode& node) {
367 if(m_polygonType == POLYLIST) {
368 return node.getChild(
"vcount").value.toIntegerVector();
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;
381 for (
int index = 0; index < weightsCount; ++index) {
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]);
389 skinData->limitJointNumber(m_maxWeight);
390 skinningData.push_back(skinData);
399Joint* DAELoader::extractMainJointData(
const XNode& jointNode,
bool isRoot) {
400 std::string nameId = jointNode.getAttribute(
"id").value;
402 auto jointOrders = m_skinningData->get_jointOrder();
403 for (
int i = 0; i < jointOrders.size(); ++i) {
404 if (trim(jointOrders[i]) == nameId) {
413 std::vector<float> matrixData = jointNode.getChild(
"matrix").value.toFloatVector();
415 matrix = matrix.Transposed();
418 matrix *= CORRECTION;
421 return new Joint(index, nameId, matrix);
424Joint* DAELoader::loadJointData(
const XNode& jointNode,
bool isRoot) {
425 Joint* joint = extractMainJointData(jointNode, isRoot);
428 for (
const XNode& childNode : jointNode.children) {
429 if (childNode.name ==
"node") {
430 joint->addChild(loadJointData(childNode,
false));
433 }
catch (
int error) {}
438void DAELoader::LoadTexturePath(
const XNode& imageNode) {
440 if(!imageNode.hasChild(
"image"))
return;
442 std::string path = imageNode.getChild(
"image").getChild(
"init_from").value;
444 auto asset = CORE->GetCore(
ResMgr)->GetAssetReference(path);
445 if (asset ==
nullptr)
return;
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;
458 int size = meshData->vertices.size();
459 vertices.resize(size * 3);
460 normals.resize(size * 3);
461 texUVs.resize(size * 2);
463 jointIDs.resize(size * 3);
464 weights.resize(size * 3);
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();
475 vec3 position = currentVertex.getPosition();
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;
488 if (!m_isSkinning)
continue;
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];
498 AttachDataToObjSurface(meshData->vertices.size(), vertices, normals, texUVs, meshData->indices, jointIDs, weights,
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]);
514 if (prefab ==
nullptr)
517 prefab->SetGameObject(root);
523 root->AddChild(joint_root);
524 DAEConvertSGameObject::CreateJoints(joint_root, m_skeletonData->getHeadJoint());
528 for (
const auto& mesh : m_meshList) {
530 root->AddChild(mesh_root);
539 mesh_component->SetMesh(*mesh->meshSurface);
543 joint_root_component->GetGameObject(),
544 m_skeletonData->getJointCount());
551 SGameObject* animationObj = DAEConvertSGameObject::CreateAnimation(root, joint_root_component,
552 m_animationLoader->GetAnimation(),
561 auto* loader =
new DAELoader(path, AUTO,
false);
562 auto asset = CORE->GetCore(
ResMgr)->GetAssetReference(path);
563 if (asset ==
nullptr) {
567 std::string prefab_id = asset->id;
569 loader->m_resource_id = asset->id;
570 loader->m_skeletonData = skeleton;
572 if (loader->m_skeletonData ==
nullptr) {
573 loader->m_skeletonData =
new Skeleton();
576 const auto& meshData = loader->m_meshList;
577 for (
const auto& mesh : meshData) {
578 mesh->meshSurface->LinkResource(prefab_id +
"." + mesh->meshName +
"?mesh");
580 loader->m_skeletonData->LinkResource(prefab_id +
"?skeleton");
582 loader->Load(path, AUTO);
583 prefab = loader->GeneratePrefab(animation, prefab);