LeeMcQueen / GameDemo

Demo
0 stars 0 forks source link

skeletonAnimation system ReMake #23

Open LeeMcQueen opened 3 years ago

LeeMcQueen commented 3 years ago

void AnimaModelLoader::loadAssimpScene(const char *filePath){

//导入assimp加载模组
Assimp::Importer importer;
//顶点类
std::vector<Vertex> vertices;
//顶点总数
std::vector<unsigned int> indices;
//骨骼总数
unsigned int boneCount;
//Bone骨骼类
Bone skeleton;
//顶点类
Vertex vertex;
//通过ReadFile函数得到Scene
const aiScene *scene = importer.ReadFile(filePath, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);
//Assimp加载成功判定
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
    std::cout << "ERROR::Assimp :" << importer.GetErrorString() << std::endl;
}
//Scene里的Mesh
aiMesh *mesh = scene->mMeshes[0];
//骨骼根节点的变换矩阵
globalInverseTransform_ = assimpToGlmMatrix(scene->mRootNode->mTransformation);
//变换矩阵进行反矩阵变换
setGlobaInverseTransform(glm::inverse(globalInverseTransform_));
//加载骨骼动画模型
loadAssimpModel(scene, mesh, vertices, indices, skeleton, boneCount);

//数据封装进入容器内
setVertices(vertices);
setIndices(indices);
setSkeleton(skeleton);
setBoneCount(boneCount);

};

LeeMcQueen commented 3 years ago

void AnimaModelLoader::loadAssimpModel(const aiScene scene, aiMesh mesh, std::vector &verticesOutput, std::vector &indicesOutput, Bone &skeletonOutput, unsigned int &nBoneCount){

//返回参数list初始化
verticesOutput = {};
indicesOutput = {};

//顶点类的实例化
Vertex vertex;
//加载顶点,法线,uv坐标
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {

    //空的Vec3的变量
    glm::vec3 vector;

    //取得顶点
    vector.x = mesh->mVertices[i].x;
    vector.y = mesh->mVertices[i].y;
    vector.z = mesh->mVertices[i].z;
    vertex.setPosition(vector);

    //取得法线
    vector.x = mesh->mNormals[i].x;
    vector.y = mesh->mNormals[i].y;
    vector.z = mesh->mNormals[i].z;
    vertex.setNormal(vector);

    //空的Vec2的变量
    glm::vec2 vec;

    //注意这里就只有一个纹理,需要的话需要动态设定
    vec.x = mesh->mTextureCoords[0][i].x;
    vec.y = mesh->mTextureCoords[0][i].y;
    vertex.setTexture(vec);

    //初始化骨骼ID 一共创建顶点的数量个
    vertex.setBoneIds(glm::ivec4(0));
    vertex.setBoneWeights(glm::vec4(0.0f));

    verticesOutput.push_back(vertex);
}

//加载骨骼数据到顶点数组
//boneInfo的结构是 骨骼名<string> 矩阵pair
std::unordered_map<std::string, std::pair<int, glm::mat4>> boneInfo = {};
std::vector<unsigned int> boneCounts;
//命名感觉不是很准确 顶点数同样数量的list
boneCounts.resize(verticesOutput.size(), 0);
//得到模型的总骨骼数
nBoneCount = mesh->mNumBones;

std::cout << "loadModel() nBoneCount" << nBoneCount << std::endl;

//循环骨骼数量得到()
for (unsigned int i = 0; i < nBoneCount; i++) {

    //导入aiMesh对象中的顶点骨骼数据
    aiBone *bone = mesh->mBones[i];
    //从Assimp格式转换成glm格式
    glm::mat4 matrix = assimpToGlmMatrix(bone->mOffsetMatrix);
    //按照骨骼名称(string形式)往里面注入map, map的形式是(i, matrix)
    boneInfo[bone->mName.C_Str()] = { i, matrix };

    //循环骨骼里面的顶点(通过总权重数就知道有多少个顶点)
    for (unsigned int j = 0; j < bone->mNumWeights; j++) {
        //当前骨骼的顶点ID
        unsigned int id = bone->mWeights[j].mVertexId;
        //当前骨骼的顶点的权重值
        float weight = bone->mWeights[j].mWeight;
        boneCounts[id]++;

        //根据
        switch (boneCounts[id])
        {
        case 1:
            verticesOutput[id].setBoneIds_x(i);
            verticesOutput[id].setBoneWeights_x(weight);
            break;
        case 2:
            verticesOutput[id].setBoneIds_y(i);
            verticesOutput[id].setBoneWeights_y(weight);
            break;
        case 3:
            verticesOutput[id].setBoneIds_z(i);
            verticesOutput[id].setBoneWeights_z(weight);
            break;
        case 4:
            verticesOutput[id].setBoneIds_w(i);
            verticesOutput[id].setBoneWeights_w(weight);
            break;

        default:
            break;
        }
    }
}

//让所有权重的和为1
for (unsigned int i = 0; i < verticesOutput.size(); i++) {
    //取得所有顶点数组里面的骨骼权重
    glm::vec4 &boneWeight = verticesOutput[i].getBoneWieghts();

    float totalWeight = boneWeight.x + boneWeight.y + boneWeight.z + boneWeight.w;
    if (totalWeight > 0.0f) {
        verticesOutput[i].setBoneWeights(glm::vec4(
            boneWeight.x / totalWeight,
            boneWeight.y / totalWeight,
            boneWeight.z / totalWeight,
            boneWeight.w / totalWeight)
        );
    }
}

for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
    aiFace &face = mesh->mFaces[i];
    for (unsigned int j = 0; j < face.mNumIndices; j++) {
        indicesOutput.push_back(face.mIndices[j]);
    }
}

readSkeleton(skeletonOutput, scene->mRootNode, boneInfo);

}