void BlenderSceneExporter::storeSkeletons( TamySkeleton* arrSkeletons, int skeletonsCount ) { ResourcesManager& resMgr = TSingleton< ResourcesManager >::getInstance(); m_exportedSkeletons.clear(); m_exportedSkeletons.resize( skeletonsCount ); Matrix boneLocalMtx; for ( int skeletonIdx = 0; skeletonIdx < skeletonsCount; ++skeletonIdx ) { const TamySkeleton& exportedSkeleton = arrSkeletons[skeletonIdx]; FilePath skeletonPath( m_animationsExportDir + exportedSkeleton.name + "." + Skeleton::getExtension() ); Skeleton* skeleton = resMgr.create< Skeleton >( skeletonPath ); skeleton->clear(); m_exportedSkeletons[skeletonIdx] = skeleton; // set skeleton bones for ( int boneIdx = 0; boneIdx < exportedSkeleton.bonesCount; ++boneIdx ) { const TamyBone& exportedBone = exportedSkeleton.bones[boneIdx]; Matrix boneLocalTransform, invBoneMSTransform; if ( exportedBone.parentBoneIdx >= 0 ) { const TamyBone& parentBone = exportedSkeleton.bones[exportedBone.parentBoneIdx]; parentBone.modelSpaceTransform.applyTo( invBoneMSTransform ); invBoneMSTransform.invert(); Matrix boneMSTransform; exportedBone.modelSpaceTransform.applyTo( boneMSTransform ); boneLocalTransform.setMul( boneMSTransform, invBoneMSTransform ); } else { exportedBone.modelSpaceTransform.applyTo( boneLocalTransform ); } skeleton->addBone( exportedBone.name, boneLocalTransform, exportedBone.parentBoneIdx, exportedBone.boneLength ); } // calculate skeleton's bind pose skeleton->buildSkeleton(); // save the skeleton if ( m_exportSettings.saveAnimations ) { skeleton->saveResource(); } } }
bool FileSystem::loadModelAndSkeletonDae(const char *path, Model &m, Skeleton &s) { size_t pos; std::string line, armatureName; std::ifstream fileStream(path); std::vector<bool> closed; glm::mat4 bindShapeMatrix; std::vector<float> v, n, t, w; std::vector<glm::mat4> bindPoses; std::vector<std::vector<int> > weightJoints, weightWeights, indices; std::vector<std::string> polylistMaterials; std::vector<int> vcount; if (fileStream.is_open()) { getline(fileStream, line); while (line.find("<library_geometries>") == std::string::npos && fileStream.good()) { getline(fileStream, line); } while (line.find("<mesh>") == std::string::npos && fileStream.good()) { getline(fileStream, line); } //load model while (fileStream.good()) { getline(fileStream, line); size_t pos; if ((pos = line.find("<source id=")) != std::string::npos) { std::string id = line; getline(fileStream, line); std::string::iterator begIt = line.begin() + (pos = line.find_first_of(">")) + 1; std::string::iterator endIt = line.begin() + line.find_first_of("<", pos + 1); if ((pos = id.find("-positions")) != std::string::npos) { v.reserve(atoi(line.substr((pos = line.find("count=\"")) + 7, line.find_first_of("\"", pos + 1) - (pos + 1)).c_str())); split(begIt, endIt, ' ', v); } else if ((pos = id.find("-normals")) != std::string::npos) { n.reserve(atoi(line.substr((pos = line.find("count=\"")) + 7, line.find_first_of("\"", pos + 1) - (pos + 1)).c_str())); split(begIt, endIt, ' ', n); } else if ((pos = id.find("-map")) != std::string::npos) { t.reserve(atoi(line.substr((pos = line.find("count=\"")) + 7, line.find_first_of("\"", pos + 1) - (pos + 1)).c_str())); split(begIt, endIt, ' ', t); } } else if ((pos = line.find("<polylist")) != std::string::npos) { polylistMaterials.push_back(line.substr((pos = line.find("material=\"") + 10), line.find("-material\"", pos + 1) - pos)); indices.push_back(std::vector<int>()); indices.back().reserve(atoi(line.substr((pos = line.find("count=\"")) + 7, line.find_first_of("\"", pos + 1) - (pos + 1)).c_str())); while (line.find("<p>") == std::string::npos && fileStream.good()) { getline(fileStream, line); } std::string::iterator begIt = line.begin() + (pos = line.find_first_of(">")) + 1; std::string::iterator endIt = line.begin() + line.find_first_of("<", pos + 1); split(begIt, endIt, ' ', indices.back()); } else if ((pos = line.find("</mesh>")) != std::string::npos) { break; } } while (line.find("<library_controllers>") == std::string::npos && fileStream.good()) { getline(fileStream, line); } while (line.find("</library_controllers>") == std::string::npos && fileStream.good()) { if (line.find("<controller id") != std::string::npos) { if ((pos = line.find("-skin\"")) != std::string::npos) { pos = line.find("name="); armatureName = line.substr((pos = line.find_first_of("\"", pos)) + 1, line.find_first_of("\"", pos + 1) - (pos + 1)); break; } } getline(fileStream, line); } while (line.find("<bind_shape_matrix>") == std::string::npos && fileStream.good()) { getline(fileStream, line); } { std::string::iterator begIt = line.begin() + (pos = line.find_first_of(">")) + 1; std::string::iterator endIt = line.begin() + line.find_first_of("<", pos + 1); std::vector<float> matrixValues; split(begIt, endIt, ' ', matrixValues); for (unsigned int i = 0; i < 16; i++) bindShapeMatrix[i / 4][i % 4] = matrixValues[i]; bindShapeMatrix = glm::transpose(bindShapeMatrix); } //load vertex weights while (fileStream.good()) { getline(fileStream, line); if ((pos = line.find("<source id=")) != std::string::npos) { getline(fileStream, line); std::string::iterator begIt = line.begin() + (pos = line.find_first_of(">")) + 1; std::string::iterator endIt = line.begin() + line.find_first_of("<", pos + 1); if ((pos = line.find("-bind_poses-array")) != std::string::npos) { std::vector<float> matrixValues; matrixValues.reserve(atoi(line.substr((pos = line.find("count=\"")) + 7, line.find_first_of("\"", pos + 1) - (pos + 1)).c_str())); split(begIt, endIt, ' ', matrixValues); for (unsigned int i = 0; i < matrixValues.size(); i++) { glm::mat4 m; for (int j = 0; j < 16; j++) { m[j / 4][j % 4] = matrixValues[i]; i++; } i--; bindPoses.push_back(m); } } else if ((pos = line.find("-weights-array")) != std::string::npos) { w.reserve(atoi(line.substr((pos = line.find("count=\"")) + 7, line.find_first_of("\"", pos + 1) - (pos + 1)).c_str())); split(begIt, endIt, ' ', w); } } else if (line.find("<vertex_weights") != std::string::npos) break; } int weightsCount = atoi(line.substr((pos = line.find("count=\"")) + 7, line.find_first_of("\"", pos + 1) - (pos + 1)).c_str()); while (line.find("<vcount>") == std::string::npos && fileStream.good()) { getline(fileStream, line); } std::string::iterator begIt = line.begin() + (pos = line.find_first_of(">")) + 1; std::string::iterator endIt = line.begin() + line.find_first_of("<", pos + 1); vcount.reserve(weightsCount); split(begIt, endIt, ' ', vcount); while (line.find("<v>") == std::string::npos && fileStream.good()) { getline(fileStream, line); } begIt = line.begin() + (pos = line.find_first_of(">")) + 1; endIt = line.begin() + line.find_first_of("<", pos + 1); std::vector<int> weights; weights.reserve(weightsCount); split(begIt, endIt, ' ', weights); int k = 0; weightJoints.reserve(vcount.size()); weightWeights.reserve(vcount.size()); for (unsigned int i = 0; i < vcount.size(); i++) { weightJoints.push_back(std::vector<int>()); weightJoints.back().reserve(vcount[i]); weightWeights.push_back(std::vector<int>()); weightWeights.back().reserve(vcount[i]); for (int j = 0; j < vcount[i]; j++) { weightJoints[i].push_back(weights[k]); k++; weightWeights[i].push_back(weights[k]); k++; } } while (line.find("<library_visual_scenes>") == std::string::npos && fileStream.good()) { getline(fileStream, line); } while (line.find("node id=\"" + armatureName + "\"") == std::string::npos && fileStream.good()) { getline(fileStream, line); } getline(fileStream, line); { std::string::iterator begIt = line.begin() + (pos = line.find_first_of(">")) + 1; std::string::iterator endIt = line.begin() + line.find_first_of("<", pos + 1); std::vector<float> mat; mat.reserve(16); split(begIt, endIt, ' ', mat); glm::mat4 m; for (unsigned int i = 0; i < 16; i++) m[i / 4][i % 4] = mat[i]; s.setRootTransformMatrix(glm::transpose(m)); } s.setBonesNumber(bindPoses.size()); //load skeleton while (fileStream.good()) { getline(fileStream, line); if (line.find("</node>") != std::string::npos) { int last = findLastOpen(closed); if (last < 0) break; closed[last] = true;; } else if ((pos = line.find("<node id=")) != std::string::npos) { int parent = findLastOpen(closed); std::string name = line.substr((pos = line.find_first_of("\"")) + 1, line.find_first_of("\"", pos + 1) - (pos + 1)); getline(fileStream, line); std::string::iterator begIt = line.begin() + (pos = line.find_first_of(">")) + 1; std::string::iterator endIt = line.begin() + line.find_first_of("<", pos + 1); std::vector<float> mat; mat.reserve(16); split(begIt, endIt, ' ', mat); glm::mat4 m; for (unsigned int i = 0; i < 16; i++) m[i / 4][i % 4] = mat[i]; s.addBone(glm::transpose(m), findLastOpen(closed)); closed.push_back(false); } } if (!fileStream.good()) { std::cout << "File is in incorrect format " << path << std::endl; return false; } //add inverse bind pose matrices for (unsigned int i = 0; i < bindPoses.size(); i++) { s.getBone(i)->inverseBindMatrix = glm::transpose(bindPoses[i]) * bindShapeMatrix; } s.fixScale(); //sort weights std::vector<std::vector<float> > wSorted; std::vector<std::vector<int> > jSorted; wSorted.reserve(weightJoints.size()); jSorted.reserve(weightJoints.size()); for (unsigned int i = 0; i < weightJoints.size(); i++) { wSorted.push_back(std::vector<float>()); wSorted.back().reserve(weightJoints[i].size()); jSorted.push_back(std::vector<int>()); jSorted.back().reserve(weightJoints[i].size()); for (unsigned int j = 0; j < weightJoints[i].size(); j++) { if (j == 0) { wSorted[i].push_back(w[weightWeights[i][j]]); jSorted[i].push_back(weightJoints[i][j]); } else { for (unsigned int k = 0; k < wSorted[i].size(); k++) { if (w[weightWeights[i][j]] > wSorted[i][k]) { wSorted[i].insert(wSorted[i].begin() + k, w[weightWeights[i][j]]); jSorted[i].insert(jSorted[i].begin() + k, weightJoints[i][j]); break; } if (k == wSorted[i].size() - 1) { wSorted[i].push_back(w[weightWeights[i][j]]); jSorted[i].push_back(weightJoints[i][j]); break; } } } } } for (unsigned int i = 0; i < wSorted.size(); i++) { if (wSorted[i].size() > 4) { for (unsigned int j = wSorted[i].size() - 1; j > 3; j--) { for (int k = 0; k < 4; k++) wSorted[i][k] += wSorted[i][j] * 0.25f; wSorted[i].erase(wSorted[i].begin() + j); jSorted[i].erase(jSorted[i].begin() + j); } } } //push in faces for (unsigned int k = 0; k < indices.size(); k++) { WeightedMesh mesh; mesh.reserve(indices[k].size()); for (unsigned int i = 0; i < indices[k].size(); i += 3) { glm::vec3 vertex, normal; glm::vec2 texCoord; glm::vec4 weights; glm::ivec4 joints; vertex.x = v[indices[k][i] * 3]; vertex.y = v[indices[k][i] * 3 + 1]; vertex.z = v[indices[k][i] * 3 + 2]; weights = glm::vec4(0.0f); joints = glm::ivec4(0); for (unsigned int j = 0; j < wSorted[indices[k][i]].size(); j++) { weights[j] = wSorted[indices[k][i]][j]; joints[j] = jSorted[indices[k][i]][j]; } normal.x = n[indices[k][i + 1] * 3]; normal.y = n[indices[k][i + 1] * 3 + 1]; normal.z = n[indices[k][i + 1] * 3 + 2]; if (t.size() > 0) { texCoord.x = t[indices[k][i + 2] * 2]; texCoord.y = 1.0f - t[indices[k][i + 2] * 2 + 1]; //OpenGL coords } else texCoord = glm::vec2(0.0f); mesh.addVertex(vertex, normal, texCoord, weights, joints); } std::shared_ptr<Material> mat(new Material); Texture tex; if (!loadTexture(std::string("resource/").append(polylistMaterials[k].append("_D.png")).c_str(), tex)) { if (!loadTexture("resource/white_D.png", tex)) return false; } mat->setDifTex(tex); mesh.addMaterial(mat); m.addMesh(std::make_shared<WeightedMesh>(mesh)); } fileStream.close(); return true; } std::cout << "Unable to open file " << path << std::endl; return false; }