コード例 #1
1
ファイル: BlenderSceneExporter.cpp プロジェクト: dabroz/Tamy
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();
      }
   }
}
コード例 #2
0
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;
}