SkeletalMeshComponent.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // ----------------------------------------------------------------
  2. // From Game Programming in C++ by Sanjay Madhav
  3. // Copyright (C) 2017 Sanjay Madhav. All rights reserved.
  4. //
  5. // Released under the BSD License
  6. // See LICENSE in root directory for full details.
  7. // ----------------------------------------------------------------
  8. #include "SkeletalMeshComponent.h"
  9. #include "Shader.h"
  10. #include "Mesh.h"
  11. #include "Actor.h"
  12. #include "Game.h"
  13. #include "Renderer.h"
  14. #include "Texture.h"
  15. #include "VertexArray.h"
  16. #include "Animation.h"
  17. #include "Skeleton.h"
  18. #include "LevelLoader.h"
  19. SkeletalMeshComponent::SkeletalMeshComponent(Actor* owner)
  20. :MeshComponent(owner, true)
  21. ,mSkeleton(nullptr)
  22. {
  23. }
  24. void SkeletalMeshComponent::Draw(Shader* shader)
  25. {
  26. if (mMesh)
  27. {
  28. // Set the world transform
  29. shader->SetMatrixUniform("uWorldTransform",
  30. mOwner->GetWorldTransform());
  31. // Set the matrix palette
  32. shader->SetMatrixUniforms("uMatrixPalette", &mPalette.mEntry[0],
  33. MAX_SKELETON_BONES);
  34. // Set specular power
  35. shader->SetFloatUniform("uSpecPower", mMesh->GetSpecPower());
  36. // Set the active texture
  37. Texture* t = mMesh->GetTexture(mTextureIndex);
  38. if (t)
  39. {
  40. t->SetActive();
  41. }
  42. // Set the mesh's vertex array as active
  43. VertexArray* va = mMesh->GetVertexArray();
  44. va->SetActive();
  45. // Draw
  46. glDrawElements(GL_TRIANGLES, va->GetNumIndices(), GL_UNSIGNED_INT, nullptr);
  47. }
  48. }
  49. void SkeletalMeshComponent::Update(float deltaTime)
  50. {
  51. if (mAnimation && mSkeleton)
  52. {
  53. mAnimTime += deltaTime * mAnimPlayRate;
  54. // Wrap around anim time if past duration
  55. while (mAnimTime > mAnimation->GetDuration())
  56. {
  57. mAnimTime -= mAnimation->GetDuration();
  58. }
  59. // Recompute matrix palette
  60. ComputeMatrixPalette();
  61. }
  62. }
  63. float SkeletalMeshComponent::PlayAnimation(Animation* anim, float playRate)
  64. {
  65. mAnimation = anim;
  66. mAnimTime = 0.0f;
  67. mAnimPlayRate = playRate;
  68. if (!mAnimation) { return 0.0f; }
  69. ComputeMatrixPalette();
  70. return mAnimation->GetDuration();
  71. }
  72. void SkeletalMeshComponent::LoadProperties(const rapidjson::Value& inObj)
  73. {
  74. MeshComponent::LoadProperties(inObj);
  75. std::string skelFile;
  76. if (JsonHelper::GetString(inObj, "skelFile", skelFile))
  77. {
  78. SetSkeleton(mOwner->GetGame()->GetSkeleton(skelFile));
  79. }
  80. std::string animFile;
  81. if (JsonHelper::GetString(inObj, "animFile", animFile))
  82. {
  83. PlayAnimation(mOwner->GetGame()->GetAnimation(animFile));
  84. }
  85. JsonHelper::GetFloat(inObj, "animPlayRate", mAnimPlayRate);
  86. JsonHelper::GetFloat(inObj, "animTime", mAnimTime);
  87. }
  88. void SkeletalMeshComponent::SaveProperties(rapidjson::Document::AllocatorType& alloc, rapidjson::Value& inObj) const
  89. {
  90. MeshComponent::SaveProperties(alloc, inObj);
  91. if (mSkeleton)
  92. {
  93. JsonHelper::AddString(alloc, inObj, "skelFile", mSkeleton->GetFileName());
  94. }
  95. if (mAnimation)
  96. {
  97. JsonHelper::AddString(alloc, inObj, "animFile", mAnimation->GetFileName());
  98. }
  99. JsonHelper::AddFloat(alloc, inObj, "animPlayRate", mAnimPlayRate);
  100. JsonHelper::AddFloat(alloc, inObj, "animTime", mAnimTime);
  101. }
  102. void SkeletalMeshComponent::ComputeMatrixPalette()
  103. {
  104. const std::vector<Matrix4>& globalInvBindPoses = mSkeleton->GetGlobalInvBindPoses();
  105. std::vector<Matrix4> currentPoses;
  106. mAnimation->GetGlobalPoseAtTime(currentPoses, mSkeleton, mAnimTime);
  107. // Setup the palette for each bone
  108. for (size_t i = 0; i < mSkeleton->GetNumBones(); i++)
  109. {
  110. // Global inverse bind pose matrix times current pose matrix
  111. mPalette.mEntry[i] = globalInvBindPoses[i] * currentPoses[i];
  112. }
  113. }