c++ - FBX Sdk Skeletal Animations -


i have loaded , rendered fbx model using fbx sdk , directx. i'm trying implement skeletal animations. first i'm trying put character on different poses modifying bones matrices. (so can achieve animations setting different poses @ times)

here's code of loading fbx , skinning information.

fbxloader.h

#include <fbxsdk.h> #include <vector> #include <string> #include <map> #include <d3d11_1.h> #include <directxmath.h> #include "textureloader.h"  using namespace directx;  struct vertex {     xmfloat3 pos;     xmfloat2 tex;     xmfloat4 boneids;     xmfloat4 weights;      vertex()     {         boneids = { 0, 0, 0, 0 };         weights = { 0, 0, 0, 0 };     } };  struct keyframe {     fbxlonglong mframenum;     fbxamatrix mglobaltransform;     keyframe* mnext;      keyframe() : mnext(nullptr)     {} };  struct joint { int mparentindex; const char* mname; fbxamatrix mglobalbindposeinverse; keyframe* manimation; fbxnode *mnode;  joint() :     mnode(nullptr),     manimation(nullptr) {     mglobalbindposeinverse.setidentity();     mparentindex = -1; }  ~joint() {     while (manimation)     {         keyframe* temp = manimation->mnext;         delete manimation;         manimation = temp;     } } };  struct skeleton { std::vector<joint> mjoints; };  class mesh { public: mesh(id3d11device *dev, std::vector<vertex> vertices, id3d11shaderresourceview *texture) {     this->vertices = vertices;     this->texture = texture;      this->setupmesh(dev); }  void draw(id3d11devicecontext *devcon) {     uint stride = sizeof(vertex);     uint offset = 0;      devcon->iasetvertexbuffers(0, 1, &vertexbuffer, &stride, &offset);      if (this->texture != nullptr)         devcon->pssetshaderresources(0, 1, &texture);      devcon->draw(vertices.size(), 0); } private: std::vector<vertex> vertices; id3d11shaderresourceview *texture = nullptr; id3d11buffer* vertexbuffer;  bool setupmesh(id3d11device *dev) {     hresult hr;      d3d11_buffer_desc vbd;     vbd.usage = d3d11_usage_immutable;     vbd.bytewidth = sizeof(vertex) * vertices.size();     vbd.bindflags = d3d11_bind_vertex_buffer;     vbd.cpuaccessflags = 0;     vbd.miscflags = 0;      d3d11_subresource_data initdata;     initdata.psysmem = &vertices[0];      hr = dev->createbuffer(&vbd, &initdata, &vertexbuffer);     if (failed(hr))         return false; } };  class fbxloader { public: fbxloader(); ~fbxloader();  void loadfbx(hwnd hwnd, id3d11device *dev, id3d11devicecontext *devcon, const char* filename);  void draw(id3d11devicecontext *devcon);  xmmatrix getanimatedmatrix(int index);  skeleton skeleton;  private: fbxmanager *fbxsdkmanager = nullptr; fbxscene *fbxscene; std::map<int, int> controlpoints; std::vector<mesh> meshes; hwnd hwnd;  void processnode(id3d11device *dev, id3d11devicecontext *devcon, fbxnode *node, fbxgeometryconverter *gconverter);  mesh processmesh(id3d11device* dev, id3d11devicecontext *devcon, fbxmesh *mesh);  void processskeletonheirarchy(fbxnode* rootnode);  void processskeletonheirarchyre(fbxnode* node, int depth, int index, int parentindex);  unsigned int findjointindex(const std::string& jointname);  id3d11shaderresourceview *loadtexture(id3d11device *dev, id3d11devicecontext *devcon, const char* texturefilename); }; 

fbxloader.cpp

#include "fbxloader.h"    fbxloader::fbxloader() { }   fbxloader::~fbxloader() { }  void fbxloader::loadfbx(hwnd hwnd, id3d11device * dev, id3d11devicecontext *devcon, const char * filename) { if (fbxsdkmanager == nullptr) {     fbxsdkmanager = fbxmanager::create();      fbxiosettings* iosettings = fbxiosettings::create(fbxsdkmanager, iosroot);     fbxsdkmanager->setiosettings(iosettings); }  fbximporter *importer = fbximporter::create(fbxsdkmanager, ""); fbxscene = fbxscene::create(fbxsdkmanager, "");  fbxgeometryconverter gconverter(fbxsdkmanager);  bool bsuccess = importer->initialize(filename, -1, fbxsdkmanager->getiosettings());  bsuccess = importer->import(fbxscene);  importer->destroy();  fbxnode *fbxrootnode = fbxscene->getrootnode();  processskeletonheirarchy(fbxrootnode);  this->hwnd = hwnd;  processnode(dev, devcon, fbxrootnode, &gconverter); }  void fbxloader::draw(id3d11devicecontext * devcon) { (int = 0; < meshes.size(); i++) {     meshes[i].draw(devcon); } }  xmmatrix fbxloader::getanimatedmatrix(int index) { xmmatrix bonematxm; fbxamatrix bonemat = skeleton.mjoints[index].mglobalbindposeinverse; //* skeleton.mjoints[0].manimation->mglobaltransform;  bonematxm = xmmatrixtranslation(bonemat.gett().mdata[0], bonemat.gett().mdata[1], bonemat.gett().mdata[2]); bonematxm *= xmmatrixrotationx(bonemat.getr().mdata[0]); bonematxm *= xmmatrixrotationy(bonemat.getr().mdata[1]); bonematxm *= xmmatrixrotationz(bonemat.getr().mdata[2]);  return bonematxm; }  void fbxloader::processnode(id3d11device * dev, id3d11devicecontext *devcon, fbxnode * node, fbxgeometryconverter * gconverter) { if (node) {     if (node->getnodeattribute() != nullptr)     {         fbxnodeattribute::etype attributetype = node->getnodeattribute()->getattributetype();          if (attributetype == fbxnodeattribute::emesh)         {             fbxmesh *mesh;              mesh = (fbxmesh*)gconverter->triangulate(node->getnodeattribute(), true);              meshes.push_back(processmesh(dev, devcon, mesh));         }     }      (int = 0; < node->getchildcount(); i++)     {         processnode(dev, devcon, node->getchild(i), gconverter);     } } }  mesh fbxloader::processmesh(id3d11device * dev, id3d11devicecontext *devcon, fbxmesh * mesh) { std::vector<vertex> meshvertices; id3d11shaderresourceview *meshtexture = nullptr;  fbxvector4 *vertices = mesh->getcontrolpoints();  (int j = 0; j < mesh->getpolygoncount(); j++) {     int numvertices = mesh->getpolygonsize(j);      fbxlayerelementarraytemplate<fbxvector2> *uvvertices = 0;     mesh->gettextureuv(&uvvertices, fbxlayerelement::etexturediffuse);      (int k = 0; k < numvertices; k++)     {         int controlpointindex = mesh->getpolygonvertex(j, k);          vertex vertex;          vertex.pos.x = (float)vertices[controlpointindex].mdata[0];         vertex.pos.y = (float)vertices[controlpointindex].mdata[1];         vertex.pos.z = (float)vertices[controlpointindex].mdata[2];          vertex.tex.x = (float)uvvertices->getat(mesh->gettextureuvindex(j, k)).mdata[0];         vertex.tex.y = 1.0f - (float)uvvertices->getat(mesh->gettextureuvindex(j, k)).mdata[1];          controlpoints[controlpointindex] = meshvertices.size();          meshvertices.push_back(vertex);     } }  int materialcount = mesh->getnode()->getsrcobjectcount<fbxsurfacematerial>();  (int = 0; < materialcount; i++) {     fbxsurfacematerial *material = (fbxsurfacematerial*)mesh->getnode()->getsrcobject<fbxsurfacematerial>(i);      if (material)     {         fbxproperty prop = material->findproperty(fbxsurfacematerial::sdiffuse);          const fbxtexture* texture = fbxcast<fbxtexture>(prop.getsrcobject<fbxtexture>(0));         const fbxfiletexture* filetexture = fbxcast<fbxfiletexture>(texture);          id3d11shaderresourceview *meshctexture = loadtexture(dev, devcon, filetexture->getfilename());          meshtexture = meshctexture;     } }  const fbxvector4 lt = mesh->getnode()->getgeometrictranslation(fbxnode::esourcepivot); const fbxvector4 lr = mesh->getnode()->getgeometricrotation(fbxnode::esourcepivot); const fbxvector4 ls = mesh->getnode()->getgeometricscaling(fbxnode::esourcepivot);  fbxamatrix geometrytransform = fbxamatrix(lt, lr, ls);  (unsigned int deformerindex = 0; deformerindex < mesh->getdeformercount(); ++deformerindex) {     fbxskin* skin = reinterpret_cast<fbxskin*>(mesh->getdeformer(deformerindex, fbxdeformer::eskin));     if (!skin)         continue;      (unsigned int clusterindex = 0; clusterindex < skin->getclustercount(); ++clusterindex)     {         fbxcluster* cluster = skin->getcluster(clusterindex);         std::string jointname = cluster->getlink()->getname();         unsigned int jointindex = findjointindex(jointname);         fbxamatrix transformmatrix;         fbxamatrix transformlinkmatrix;         fbxamatrix globalbindposeinversematrix;          cluster->gettransformmatrix(transformmatrix);         cluster->gettransformlinkmatrix(transformlinkmatrix);         globalbindposeinversematrix = transformlinkmatrix.inverse() * transformmatrix * geometrytransform;          skeleton.mjoints[jointindex].mglobalbindposeinverse = globalbindposeinversematrix;         skeleton.mjoints[jointindex].mnode = cluster->getlink();          (unsigned int = 0; < cluster->getcontrolpointindicescount(); ++i)         {             int vertexid = controlpoints[cluster->getcontrolpointindices()[i]];              if (meshvertices[vertexid].boneids.x == 0) meshvertices[vertexid].boneids.x = jointindex;             if (meshvertices[vertexid].boneids.y == 0) meshvertices[vertexid].boneids.y = jointindex;             if (meshvertices[vertexid].boneids.z == 0) meshvertices[vertexid].boneids.z = jointindex;             if (meshvertices[vertexid].boneids.w == 0) meshvertices[vertexid].boneids.w = jointindex;             if (meshvertices[vertexid].weights.x == 0) meshvertices[vertexid].weights.x = cluster->getcontrolpointweights()[i];             if (meshvertices[vertexid].weights.y == 0) meshvertices[vertexid].weights.y = cluster->getcontrolpointweights()[i];             if (meshvertices[vertexid].weights.z == 0) meshvertices[vertexid].weights.z = cluster->getcontrolpointweights()[i];             if (meshvertices[vertexid].weights.w == 0) meshvertices[vertexid].weights.w = cluster->getcontrolpointweights()[i];         }          fbxanimstack* animstack = fbxscene->getsrcobject<fbxanimstack>(0);         fbxstring animstackname = animstack->getname();         fbxtakeinfo* takeinfo = fbxscene->gettakeinfo(animstackname);         fbxtime start = takeinfo->mlocaltimespan.getstart();         fbxtime end = takeinfo->mlocaltimespan.getstop();         fbxlonglong animationlength = end.getframecount(fbxtime::eframes30) - start.getframecount(fbxtime::eframes30) + 1;         keyframe** anim = &skeleton.mjoints[jointindex].manimation;          (fbxlonglong = start.getframecount(fbxtime::eframes30); <= end.getframecount(fbxtime::eframes30); ++i)         {             fbxtime time;             time.setframe(i, fbxtime::eframes30);             *anim = new keyframe();             (*anim)->mframenum = i;             fbxamatrix transformoffset = mesh->getnode()->evaluateglobaltransform(1.0f) * geometrytransform;             (*anim)->mglobaltransform = transformoffset.inverse() * cluster->getlink()->evaluateglobaltransform(time);             anim = &((*anim)->mnext);         }     } }  return mesh(dev, meshvertices, meshtexture); }  void fbxloader::processskeletonheirarchy(fbxnode * rootnode) { (int childindex = 0; childindex < rootnode->getchildcount(); ++childindex) {     fbxnode *node = rootnode->getchild(childindex);     processskeletonheirarchyre(node, 0, 0, -1); } }  void fbxloader::processskeletonheirarchyre(fbxnode * node, int depth, int index, int parentindex) { if (node->getnodeattribute() && node->getnodeattribute()->getattributetype() && node->getnodeattribute()->getattributetype() == fbxnodeattribute::eskeleton) {     joint joint;     joint.mparentindex = parentindex;     joint.mname = node->getname();     skeleton.mjoints.push_back(joint); } (int = 0; < node->getchildcount(); i++) {     processskeletonheirarchyre(node->getchild(i), depth + 1, skeleton.mjoints.size(), index); } }  unsigned int fbxloader::findjointindex(const std::string & jointname) { (unsigned int = 0; < skeleton.mjoints.size(); ++i) {     if (skeleton.mjoints[i].mname == jointname)     {         return i;     } } }  id3d11shaderresourceview * fbxloader::loadtexture(id3d11device * dev, id3d11devicecontext * devcon, const char * texturefilename) { hresult hr;  id3d11shaderresourceview *texture;  std::string filenamestr(texturefilename); std::string sl = "/"; size_t start_pos = filenamestr.find(sl); filenamestr.replace(start_pos, sl.length(), "\\"); std::wstring filename = std::wstring(filenamestr.begin(), filenamestr.end());  hr = createwictexturefromfile(dev, devcon, filename.c_str(), nullptr, &texture); if (failed(hr))     return nullptr;  return texture; } 

here's vertex shader

matrix bonetransform = mul(bones[boneids[0]], weights[0]); bonetransform += mul(bones[boneids[1]], weights[1]); bonetransform += mul(bones[boneids[2]], weights[2]); bonetransform += mul(bones[boneids[3]], weights[3]);  float4 posl = mul(bonetransform, pos);  output.pos = mul(posl, world); 

here's drawing code

cb.mworld = xmmatrixtranspose(m_world); cb.mview = xmmatrixtranspose(m_view); cb.mprojection = xmmatrixtranspose(m_projection); (int = 0; < jasper->skeleton.mjoints.size(); i++)     cb.bones[i] = xmmatrixtranspose(xmmatrixidentity()); devcon->updatesubresource(pconstantbuffer, 0, nullptr, &cb, 0, 0);  devcon->vssetshader(pvs, 0, 0); devcon->vssetconstantbuffers(0, 1, &pconstantbuffer); devcon->pssetshader(pps, 0, 0); devcon->pssetsamplers(0, 1, &texsamplerstate); model->draw(devcon); 

and when set bones matrices in vertex shader identity matrix get.

enter image description here

shouldn't when use identity matrix?

enter image description here


Comments

Popular posts from this blog

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

python Tkinter Capturing keyboard events save as one single string -

sql server - Why does Linq-to-SQL add unnecessary COUNT()? -