forked from gameprogcpp/code
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSkeletalMeshComponent.cpp
More file actions
132 lines (113 loc) · 3.39 KB
/
SkeletalMeshComponent.cpp
File metadata and controls
132 lines (113 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// ----------------------------------------------------------------
// 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"
#include "LevelLoader.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(Animation* anim, float playRate)
{
mAnimation = anim;
mAnimTime = 0.0f;
mAnimPlayRate = playRate;
if (!mAnimation) { return 0.0f; }
ComputeMatrixPalette();
return mAnimation->GetDuration();
}
void SkeletalMeshComponent::LoadProperties(const rapidjson::Value& inObj)
{
MeshComponent::LoadProperties(inObj);
std::string skelFile;
if (JsonHelper::GetString(inObj, "skelFile", skelFile))
{
SetSkeleton(mOwner->GetGame()->GetSkeleton(skelFile));
}
std::string animFile;
if (JsonHelper::GetString(inObj, "animFile", animFile))
{
PlayAnimation(mOwner->GetGame()->GetAnimation(animFile));
}
JsonHelper::GetFloat(inObj, "animPlayRate", mAnimPlayRate);
JsonHelper::GetFloat(inObj, "animTime", mAnimTime);
}
void SkeletalMeshComponent::SaveProperties(rapidjson::Document::AllocatorType& alloc, rapidjson::Value& inObj) const
{
MeshComponent::SaveProperties(alloc, inObj);
if (mSkeleton)
{
JsonHelper::AddString(alloc, inObj, "skelFile", mSkeleton->GetFileName());
}
if (mAnimation)
{
JsonHelper::AddString(alloc, inObj, "animFile", mAnimation->GetFileName());
}
JsonHelper::AddFloat(alloc, inObj, "animPlayRate", mAnimPlayRate);
JsonHelper::AddFloat(alloc, inObj, "animTime", mAnimTime);
}
void SkeletalMeshComponent::ComputeMatrixPalette()
{
const std::vector<Matrix4>& globalInvBindPoses = mSkeleton->GetGlobalInvBindPoses();
std::vector<Matrix4> 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];
}
}