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);