FakeTruth / SkeletalAnimation

Simple C++ implementation of skeletal animation and software skinning
MIT License
47 stars 16 forks source link

From looking at the readme it's not clear how one should load a model in bind pose #3

Open SGriffeth opened 1 month ago

SGriffeth commented 1 month ago

How would I do this?

FakeTruth commented 1 month ago

Hi SGriffeth,

It's been a long time since I looked at this project, so what I say may be incorrect.

I'm not completely sure what you mean by "load a model in bind pose", but you can load a model through Assimp whether it is in bind pose or not.

Looking at the code I don't think you can display the model in bind pose. It seems the model is always put into an animated pose, so unless you have an animation with bones in the bind pose this may not be possible without changing the code.

However you may be able to draw the meshes directly without applying the bone transformations by using GetMesh(idx) and using pVertices and pNormals instead of pTransformedVertices and pTransformedNormals.

SGriffeth commented 1 month ago

Do I use pVertices AND pIndices together if I want to draw the meshes directly or just pVertices?

Also is there a way to compute the bone transformations in the vertex shader through this library? Maybe have a weight a long with an index into an array of bone transformations as part of a vertex struct and an array of these vertex structs in the SkeletalModel class, because in graphics programming its much more expensive to do the bone transformations on the cpu like calling the Update function every frame is less efficient than doing that on the gpu.

PS: Is this what I need to to get the array of vertices and indices for the loaded model in frame 0 for example?

saModel = SA::SkeletalModel(); Assimp::Importer Importer; std::string gameDir; UtilityFunctions::getGameDirectory(gameDir); const aiScene* pScene = Importer.ReadFile((gameDir + "/" + fileName).c_str(), aiProcess_LimitBoneWeights | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType);

AssimpConverter::Convert(pScene, saModel); saModel.Update(0); std::cout << saModel.GetNumMeshes() << std::endl; std::cout << "Model to be loaded: " << (gameDir + "/" + fileName).c_str() << std::endl;

size_t numVerts = 0;
for (unsigned int i = 0; i < saModel.GetNumMeshes(); ++i)
{
    const SA::sAnimatedMesh& AnimMesh = saModel.GetMesh(i);

    numVerts += AnimMesh.NumVertices;
    vertices.resize(numVerts);
    for (unsigned int i = 0; i < AnimMesh.NumIndices; ++i)
    {
        unsigned int Index = AnimMesh.pIndices[i];
        glm::vec3 v = AnimMesh.pTransformedVertices[Index];

        indices.push_back(Index);
        vertices[Index].pos = v;
    }
}

I tried doing this but it's not working, so I want to know if my understanding of the library is wrong or if something else is going on in my program.

FakeTruth commented 1 month ago

Do I use pVertices AND pIndices together if I want to draw the meshes directly or just pVertices?

I think you have to use them together yes.

Also is there a way to compute the bone transformations in the vertex shader through this library? Maybe have a weight a long with an index into an array of bone transformations as part of a vertex struct and an array of these vertex structs in the SkeletalModel class, because in graphics programming its much more expensive to do the bone transformations on the cpu like calling the Update function every frame is less efficient than doing that on the gpu.

No, the point of this library is to be relatively simple and deployable on any kind of hardware. There is no focus on performance and optimizations. If you're looking to do GPU skinning you may be better off using a different library or rolling your own, maybe in combination with this library.

PS: Is this what I need to to get the array of vertices and indices for the loaded model in frame 0 for example?

....

I tried doing this but it's not working, so I want to know if my understanding of the library is wrong or if something else is going on in my program.

It looks about right to me, what are the results you're getting and how are you rendering? Some other things I can think of: