Beispiel #1
0
/* WARNING::Vertex vector must be sorted according to aimesh indices or shit goes south */
void load_mesh_bones(const aiMesh* mesh, 
						std::unordered_map<GLuint, GLuint>& bone_map,
						std::unordered_map<std::string, GLuint>& bone_id_map,
						std::vector<Vertex>& vertices,
						std::vector<glm::mat4>& bone_info){
	for (GLuint i = 0 ; i < mesh->mNumBones; ++i) { 
		GLuint bone_index = 0; 
		GLuint bone_id = 0;
		std::string bone_name(mesh->mBones[i]->mName.data);

		if (bone_id_map.find(bone_name) == bone_id_map.end()) {
			bone_id = bone_id_map.size();
			bone_id_map[bone_name] = bone_id;
		}
		else{
			bone_id = bone_id_map[bone_name];
		}

		if (bone_map.find(bone_id) == bone_map.end()) {

			aiMatrix4x4 offset_aimatrix = mesh->mBones[i]->mOffsetMatrix;
			glm::mat4 offsetmatrix;

			for (GLuint x = 0; x < 4; ++x) {
				for (GLuint y = 0; y < 4; ++y) {
					offsetmatrix[x][y] = offset_aimatrix[x][y];
				}
			}

			bone_index = bone_info.size();
			bone_info.push_back(offsetmatrix);
			bone_map[bone_id] = bone_index;

		}


		for (GLuint j = 0 ; j < mesh->mBones[i]->mNumWeights; ++j) {
			/* TODO::Make sure this gets the right vertex id */
			GLuint vertex_id = mesh->mBones[i]->mWeights[j].mVertexId;
			GLfloat weight = mesh->mBones[i]->mWeights[j].mWeight; 
			if (!add_bone_to_vertex(vertices[vertex_id], bone_index)){
				std::cout << __FILE__ << ":" << __LINE__ << ": " << "FATAL ERROR: Vertex can only be affected by four bones, id overflow in bone: " << bone_name << std::endl;
				errorlogger("FATAL ERROR: Vertex can only be affected by four bones, id overflow in bone: ", bone_name.c_str());
				exit(EXIT_FAILURE);
			}
			if (!add_weight_to_vertex(vertices[vertex_id], weight)) {
				std::cout << __FILE__ << ":" << __LINE__ << ": " << "ERROR: Vertex can only be affected by four bones, weight overflow in bone: " << bone_name << std::endl;
				errorlogger("ERROR: Vertex can only be affected by four bones, weight overflow in bone: ", bone_name.c_str());
				exit(EXIT_FAILURE);
			}
		}
	}
}
Beispiel #2
0
Animation* ModelInterface::loadAnimation(const aiAnimation* ai_animation, const int index)
{
    QString animation_name(ai_animation->mName.data);

    double duration = ai_animation->mDuration;
    //qDebug() << "Animation: " + animation_name + " duration " + QString::number(duration);

    Animation* animation = new Animation(animation_name, duration, index);
    animation->setBoneCount(bones->getBoneNames().size());

    for(uint bone_index = 0; bone_index < ai_animation->mNumChannels; ++bone_index)
    {
        aiNodeAnim* channel = ai_animation->mChannels[bone_index];

        QString bone_name(channel->mNodeName.data);

        if(!bones->hasBone(bone_name))
            continue;

        int bone_id = bones->getBone(bone_name)->getId();

        animation->registerBone(bone_id);

        for(uint i = 0; i < channel->mNumPositionKeys; ++i)
        {
            aiVectorKey pos_key = channel->mPositionKeys[i];

            animation->addBonePosition(bone_id, float(pos_key.mTime), QVector3D(pos_key.mValue.x, pos_key.mValue.y, pos_key.mValue.z));
        }

        for(uint i = 0; i < channel->mNumRotationKeys; ++i)
        {
            aiQuatKey rot_key = channel->mRotationKeys[i];

            animation->addBoneRotation(bone_id, float(rot_key.mTime), QQuaternion(rot_key.mValue.w, rot_key.mValue.x, rot_key.mValue.y, rot_key.mValue.z));
        }

        for(uint i = 0; i < channel->mNumScalingKeys; ++i)
        {
            aiVectorKey scale_key = channel->mScalingKeys[i];

            animation->addBoneScaling(bone_id, float(scale_key.mTime), QVector3D(scale_key.mValue.x, scale_key.mValue.y, scale_key.mValue.z));
        }
    }

    return animation;
}
Beispiel #3
0
Bones* ModelInterface::loadBones(const aiScene* scene)
{
    Bones* bones = new Bones();

    for(uint mesh_index = 0; mesh_index < scene->mNumMeshes; ++mesh_index)
    {
        aiMesh* ai_mesh = scene->mMeshes[mesh_index];

        if(ai_mesh->HasBones())
        {
            for(uint bone_index = 0; bone_index < ai_mesh->mNumBones; ++bone_index)
            {
                aiBone* ai_bone = ai_mesh->mBones[bone_index];

                QString bone_name(ai_bone->mName.data);

                if(!bones->hasBone(bone_name))
                    bones->createEmptyBone(bone_name, getMatrix(&ai_bone->mOffsetMatrix));
            }
        }
    }

    return bones;
}
Beispiel #4
0
Bone::Bone(FbxScene& scene) {
  //construct hierarchy
  *this = Bone { *(scene.GetRootNode()) };

  std::map<std::string, std::pair<unsigned int, scm::math::mat4f> > bone_info{}
  ;
  unsigned num_bones = 0;
  for (unsigned int i = 0; i < scene.GetGeometryCount(); i++) {
    FbxGeometry* geo = scene.GetGeometry(i);
    if (geo->GetAttributeType() == FbxNodeAttribute::eMesh) {

      //check for skinning, use first skin deformer
      FbxSkin* skin;
      for (unsigned i = 0; i < geo->GetDeformerCount(); ++i) {
        FbxDeformer* defPtr = { geo->GetDeformer(i) };
        if (defPtr->GetDeformerType() == FbxDeformer::eSkin) {
          skin = static_cast<FbxSkin*>(defPtr);
          break;
        }
      }

      if (!skin) {
        Logger::LOG_ERROR << "Mesh does not contain skin deformer" << std::endl;
        assert(false);
      }

      //one cluster corresponds to one bone
      for (unsigned i = 0; i < skin->GetClusterCount(); ++i) {
        FbxCluster* cluster = skin->GetCluster(i);
        FbxNode* node = cluster->GetLink();

        if (!node) {
          Logger::LOG_ERROR << "associated node does not exist!" << std::endl;
          assert(false);
        }

        std::string bone_name(node->GetName());
        //helper to check for matrix magnitude
        auto magnitude = [](scm::math::mat4f const & mat)->float {
          float mag = 0.0f;
          for (unsigned i = 0; i < 16; ++i) {
            mag += mat[i] * mat[i];
          }
          return mag;
        }
        ;

        //reference pose of bone
        FbxAMatrix bind_transform;
        cluster->GetTransformLinkMatrix(bind_transform);
        //check if the clusters have an extra transformation
        FbxAMatrix cluster_transform;
        cluster->GetTransformMatrix(cluster_transform);
        if (magnitude(to_gua::mat4f(cluster_transform) -
                      scm::math::mat4f::identity()) > 0.000000001f) {
          Logger::LOG_WARNING
              << "weight cluster of bone '" << bone_name
              << "' has transformation, animation will be skewed" << std::endl;
        }
        //add bone to list if it is not already included
        if (bone_info.find(bone_name) == bone_info.end()) {
          bone_info[bone_name] = std::make_pair(
              num_bones,
              to_gua::mat4f(bind_transform.Inverse() * cluster_transform));
          ++num_bones;
        }
      }

      // traverse hierarchy and set accumulated values in the bone
      this->set_properties(bone_info);
    }
  }
}