// ---------------------------------------------------------------- // From Game Programming in C++ by Sanjay Madhav // Copyright (C) 2017 Sanjay Madhav. All rights reserved. // // Released under the BSD License // See LICENSE in root directory for full details. // ---------------------------------------------------------------- #include "SkeletalMeshComponent.h" #include "Shader.h" #include "Mesh.h" #include "Actor.h" #include "Game.h" #include "Renderer.h" #include "Texture.h" #include "VertexArray.h" #include "Animation.h" #include "Skeleton.h" SkeletalMeshComponent::SkeletalMeshComponent(Actor* owner) :MeshComponent(owner, true) ,mSkeleton(nullptr) { } void SkeletalMeshComponent::Draw(Shader* shader) { if (mMesh) { // Set the world transform shader->SetMatrixUniform("uWorldTransform", mOwner->GetWorldTransform()); // Set the matrix palette shader->SetMatrixUniforms("uMatrixPalette", &mPalette.mEntry[0], MAX_SKELETON_BONES); // Set specular power shader->SetFloatUniform("uSpecPower", mMesh->GetSpecPower()); // Set the active texture Texture* t = mMesh->GetTexture(mTextureIndex); if (t) { t->SetActive(); } // Set the mesh's vertex array as active VertexArray* va = mMesh->GetVertexArray(); va->SetActive(); // Draw glDrawElements(GL_TRIANGLES, va->GetNumIndices(), GL_UNSIGNED_INT, nullptr); } } void SkeletalMeshComponent::Update(float deltaTime) { if (mAnimation && mSkeleton) { mAnimTime += deltaTime * mAnimPlayRate; // Wrap around anim time if past duration while (mAnimTime > mAnimation->GetDuration()) { mAnimTime -= mAnimation->GetDuration(); } // Recompute matrix palette ComputeMatrixPalette(); } } float SkeletalMeshComponent::PlayAnimation(const Animation* anim, float playRate) { mAnimation = anim; mAnimTime = 0.0f; mAnimPlayRate = playRate; if (!mAnimation) { return 0.0f; } ComputeMatrixPalette(); return mAnimation->GetDuration(); } void SkeletalMeshComponent::ComputeMatrixPalette() { const std::vector& globalInvBindPoses = mSkeleton->GetGlobalInvBindPoses(); std::vector currentPoses; mAnimation->GetGlobalPoseAtTime(currentPoses, mSkeleton, mAnimTime); // Setup the palette for each bone for (size_t i = 0; i < mSkeleton->GetNumBones(); i++) { // Global inverse bind pose matrix times current pose matrix mPalette.mEntry[i] = globalInvBindPoses[i] * currentPoses[i]; } }