Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 54 additions & 9 deletions include/skeletal_animations_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,82 @@
#include "skeletal_animation_data.hpp"
#include "engine_config.hpp"

/*
Let's call TPose - initial model position, without any animations
*/

// Interpolation types, none - no interpolation at all
enum class InterpolationType {
LINEAR,
NONE
};

enum class TPoseType {
BASIC,
FROMANIM
};

class SkeletalAnimationsManager {
public:
SkeletalAnimationsManager() = default;

explicit SkeletalAnimationsManager(const std::string& animationPath, Model* model);
explicit SkeletalAnimationsManager(SkeletalAnimationData* animation);
explicit SkeletalAnimationsManager(
const std::string& animationPath,
Model* model,
TPoseType tposetype = TPoseType::BASIC,
int tposeAnimIndex = 0);
explicit SkeletalAnimationsManager(
SkeletalAnimationData* animation,
TPoseType tposetype = TPoseType::BASIC);

void AddAnimation(SkeletalAnimationData* animation);
void AddAnimation(const std::string& animationPath, Model* model);

std::string GetAnimationsInfo();

void PlayImmediately(int id, bool looped);
bool IsPlaying();
// TPose or Animation -> Animation Immideately
void PlayImmediately(
int id, bool looped,
InterpolationType interpolationType = InterpolationType::LINEAR,
float interpolationTime = 0.2f);

// Animation -> TPose
void StopImmediately(
InterpolationType interpolationType = InterpolationType::LINEAR,
float interpolationTime = 0.2f);

void StopImmediately();
void Stop();
void Stop(InterpolationType interpolationType = InterpolationType::LINEAR,
float interpolationTime = 0.2f);

// Is animating or interpolating
bool IsPlaying();
// If interpolating -> -1
int GetPlayingAnimationIndex();

// Engine functions
void Update(float dt);

const std::vector<glm::mat4> &GetFinalBoneMatrices();

private:
void CalculateBoneTransform(const AssimpNodeData* node, glm::mat4 parentTransform);
void CalculateBoneTransformMatrices(
const AssimpNodeData* node, glm::mat4 parentTransform,
glm::mat4 *boneMatrices,
SkeletalAnimationData* m_CurrentAnimation, float);

std::vector<glm::mat4> m_FinalBoneMatrices;
std::vector<SkeletalAnimationData*> m_Animations;

int m_CurrentAnimationIndex;
float m_CurrentTime;
bool m_Looped;
};


// Interpolation data
bool m_Interpolating = 0;
float m_InterpolationTime;
float m_InterpolationTimeLeft;
InterpolationType m_InterpolationType;
glm::mat4* m_BonesFrom = new glm::mat4[MAX_BONES];
glm::mat4* m_BonesTo = new glm::mat4[MAX_BONES];
glm::mat4* m_BonesTPose = new glm::mat4[MAX_BONES];
};
Binary file added resources/models/Husky.glb
Binary file not shown.
150 changes: 132 additions & 18 deletions src/components/animation/skeletal_animations_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,40 @@
#include "skeletal_animations_manager.hpp"

SkeletalAnimationsManager::SkeletalAnimationsManager(SkeletalAnimationData* animation) {
SkeletalAnimationsManager::SkeletalAnimationsManager(
SkeletalAnimationData* animation,
TPoseType tposetype) {
m_FinalBoneMatrices.reserve(MAX_BONES);
for (int i = 0; i < MAX_BONES; i++) {
m_FinalBoneMatrices.push_back(glm::mat4(1.0f));
m_BonesFrom[i] = (glm::mat4(1.0f));
m_BonesTo[i] = glm::mat4(1.0f);
m_BonesTPose[i] = glm::mat4(1.0f);
}
m_Animations.push_back(animation);
m_CurrentAnimationIndex = -1;

if (tposetype == TPoseType::FROMANIM) {
CalculateBoneTransformMatrices(
&(animation->GetRootNode()), glm::mat4(1.0f), m_BonesTPose, animation, 0.0f);
for (int i = 0; i < MAX_BONES; i++) {
m_FinalBoneMatrices[i] = m_BonesFrom[i];
}
}
}

SkeletalAnimationsManager::SkeletalAnimationsManager(const std::string& animationPath, Model* model) {
SkeletalAnimationsManager::SkeletalAnimationsManager(
const std::string& animationPath,
Model* model,
TPoseType tposetype,
int tposeAnimIndex) {
m_FinalBoneMatrices.reserve(MAX_BONES);

m_CurrentAnimationIndex = -1;
for (int i = 0; i < MAX_BONES; i++) {
m_FinalBoneMatrices.push_back(glm::mat4(1.0f));
m_BonesFrom[i] = (glm::mat4(1.0f));
m_BonesTo[i] = glm::mat4(1.0f);
m_BonesTPose[i] = glm::mat4(1.0f);
}

Assimp::Importer importer;
Expand All @@ -26,7 +48,25 @@ SkeletalAnimationsManager::SkeletalAnimationsManager(const std::string& animatio
for (unsigned int i = 0; i < scene->mNumAnimations; i++) {
m_Animations.push_back(new SkeletalAnimationData(animationPath, scene, i, model));
}
m_CurrentAnimationIndex = -1;

if (tposetype == TPoseType::FROMANIM) {
if (tposeAnimIndex >= m_Animations.size()) {
Logger::Error("Can't use index for TPose Calculating, zero index will be used");
tposeAnimIndex = 0;
}
if (m_Animations.size() == 0) {
Logger::Error("Can't use zero index for TPose Calculating, no animations found");
return;
}
CalculateBoneTransformMatrices(
&(m_Animations[tposeAnimIndex]->GetRootNode()),
glm::mat4(1.0f),
m_BonesTPose,
m_Animations[tposeAnimIndex], 0.0f);
for (int i = 0; i < MAX_BONES; i++) {
m_FinalBoneMatrices[i] = m_BonesTPose[i];
}
}
}

void SkeletalAnimationsManager::AddAnimation(SkeletalAnimationData* animation) {
Expand Down Expand Up @@ -55,45 +95,91 @@ std::string SkeletalAnimationsManager::GetAnimationsInfo() {
return info;
}

void SkeletalAnimationsManager::PlayImmediately(int index, bool looped) {

void SkeletalAnimationsManager::PlayImmediately(
int index, bool looped,
InterpolationType interpolationType,
float interpolationTime) {
if (index < 0 || index >= m_Animations.size()) {
Logger::Error("Can't play animation, wrong index");
return;
}
m_CurrentAnimationIndex = index;
m_CurrentTime = 0.0f;
m_CurrentTime = 0.f;
m_Looped = looped;

if (interpolationType != InterpolationType::NONE) {
m_Interpolating = 1;
m_InterpolationType = interpolationType;
m_InterpolationTime = interpolationTime;
m_InterpolationTimeLeft = interpolationTime;
for (int i = 0; i < MAX_BONES; i++) m_BonesFrom[i] = m_FinalBoneMatrices[i];
CalculateBoneTransformMatrices(
&(m_Animations[m_CurrentAnimationIndex]->GetRootNode()),
glm::mat4(1.0f),
m_BonesTo,
m_Animations[m_CurrentAnimationIndex],
m_CurrentTime);
}
}

bool SkeletalAnimationsManager::IsPlaying() {
return m_CurrentAnimationIndex != -1;
return m_CurrentAnimationIndex != -1 || m_Interpolating;
}

void SkeletalAnimationsManager::StopImmediately() {
m_CurrentTime = 0.0f;
m_Looped = 0;
int SkeletalAnimationsManager::GetPlayingAnimationIndex() {
return m_CurrentAnimationIndex;
}

void SkeletalAnimationsManager::StopImmediately(
InterpolationType interpolationType, float interpolationTime) {
if (m_CurrentAnimationIndex == -1) {
return;
}

m_CurrentAnimationIndex = -1;
m_CurrentTime = 0.f;

if (interpolationType != InterpolationType::NONE) {
m_Interpolating = 1;
m_InterpolationType = interpolationType;
m_InterpolationTime = interpolationTime;
m_InterpolationTimeLeft = interpolationTime;
for (int i = 0; i < MAX_BONES; i++) {
m_BonesFrom[i] = m_FinalBoneMatrices[i];
m_BonesTo[i] = m_BonesTPose[i];
}
}
}

void SkeletalAnimationsManager::Stop() {
void SkeletalAnimationsManager::Stop(InterpolationType interpolationType, float interpolationTime) {
m_Looped = 0;
m_InterpolationType = interpolationType;
m_InterpolationTime = interpolationTime;
}



void SkeletalAnimationsManager::Update(float dt) {
if (m_CurrentAnimationIndex < m_Animations.size() && m_CurrentAnimationIndex >= 0) {
if (m_Interpolating) {
m_InterpolationTimeLeft -= dt;
if (m_InterpolationTimeLeft < 0) {
m_Interpolating = 0;
for (int i = 0; i < MAX_BONES; i++) {
m_FinalBoneMatrices[i] = m_BonesTo[i];
}
return;
}
for (int i = 0; i < MAX_BONES; i++) {
m_FinalBoneMatrices[i] = m_BonesFrom[i] + (m_BonesTo[i] - m_BonesFrom[i])
* ((m_InterpolationTime - m_InterpolationTimeLeft) / m_InterpolationTime);
}
} else if (m_CurrentAnimationIndex < m_Animations.size() && m_CurrentAnimationIndex >= 0) {
SkeletalAnimationData* m_CurrentAnimation = m_Animations[m_CurrentAnimationIndex];
m_CurrentTime += m_CurrentAnimation->GetTicksPerSecond() * dt;
if (m_Looped) {
m_CurrentTime = fmod(m_CurrentTime, m_CurrentAnimation->GetDuration());
} else {
if (m_CurrentTime >= m_CurrentAnimation->GetDuration()) {
m_CurrentTime = 0.0f;
for (int i = 0; i < MAX_BONES; i++) {
m_FinalBoneMatrices[i] = glm::mat4(1.0f);
}
m_CurrentAnimationIndex = -1;
StopImmediately(m_InterpolationType, m_InterpolationTime);
return;
}
}
Expand Down Expand Up @@ -129,3 +215,31 @@ void SkeletalAnimationsManager::CalculateBoneTransform(
for (int i = 0; i < node->children.size(); i++)
CalculateBoneTransform(&node->children[i], globalTransformation);
}


void SkeletalAnimationsManager::CalculateBoneTransformMatrices(
const AssimpNodeData* node, glm::mat4 parentTransform,
glm::mat4 *boneMatrices, SkeletalAnimationData* m_CurrentAnimation, float currentTime) {

std::string nodeName = node->name;
glm::mat4 nodeTransform = node->transformation;
Bone* Bone = m_CurrentAnimation->FindBone(nodeName);

if (Bone) {
Bone->Update(m_CurrentTime);
nodeTransform = Bone->GetLocalTransform();
}

glm::mat4 globalTransformation = parentTransform * nodeTransform;
auto boneInfo = m_CurrentAnimation->FindBoneInfo(nodeName);
if (boneInfo != nullptr) {
int index = boneInfo->id;
glm::mat4 offset = boneInfo->offset;
assert(index < MAX_BONES);
boneMatrices[index] = globalTransformation * offset;
}

for (int i = 0; i < node->children.size(); i++)
CalculateBoneTransformMatrices(&node->children[i], globalTransformation,
boneMatrices, m_CurrentAnimation, currentTime);
}
46 changes: 34 additions & 12 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ int main() {

auto wolfObj = engine->NewObject().SetName("Wolf");
Logger::Info("%s", wolfObj.GetName().c_str());
wolfObj.AddTransform(Vec3(5.f, -10.f, -10.f), Vec3(10.f), Mat4(1.0));
wolfObj.AddTransform(Vec3(0.f, -5.f, -10.f), Vec3(10.f), Mat4(1.0));
wolfObj.AddModel(*wolfModel);
wolfObj.AddSkeletalAnimationsManager("Wolf/Wolf-Blender-2.82a.gltf", wolfModel).PlayImmediately(3, 1);

Expand All @@ -108,6 +108,35 @@ int main() {
wolfObj.AddBehaviour<WolfBehaviour>();
}

// Shiba inu (ETO FIASKO BRATAN)
{
/* Wolf */
Model *wolfModel = Model::loadFromFile("Husky.glb", skeletalShaderProgram);
auto wolfObj = engine->NewObject();
Logger::Info("%s", wolfObj.GetName().c_str());
wolfObj.AddTransform(Vec3(5.f, -5.f, -2.f), Vec3(1.f), Mat4(1.0));
wolfObj.AddModel(*wolfModel);
wolfObj.AddSkeletalAnimationsManager("Husky.glb", wolfModel, TPoseType::FROMANIM, 0);

class WolfBehaviour : public Behaviour {
public:
void Update(float dt) override {
left -= dt;
if (left < 0) {
self.GetSkeletalAnimationsManager()->PlayImmediately(cur, 1);
left = delay;
cur++;
cur %= 10;
}
}

float delay = 3.0f;
float left = delay;
int cur = 8;
};

wolfObj.AddBehaviour<WolfBehaviour>();
}

{
Model * model = Model::loadFromFile(catSource);
Expand All @@ -122,13 +151,6 @@ int main() {
t.RotateGlobal(1.67f, Vec3(-1.f, 0.f, 0.f));
}

// Shiba inu (ETO FIASKO BRATAN)
Model *model = Model::loadFromFile("ShibaInu.fbx");
model->shader = standartShaderProgram;
auto dog = engine->NewObject();
dog.AddModel(*model);
dog.AddTransform(Transform(Vec3(2, -5, 0.0), Vec3(1.f), glm::radians(-90.f), Vec3(1.0f, 0.f, 0.f)));

Material material = {
4.f,
Texture("wall.png", "wallspecular.png")
Expand Down Expand Up @@ -193,13 +215,13 @@ int main() {
Mat3(Vec3(1, 0, 0), Vec3(0, 1, 0), Vec3(0, 0, 1)),
Vec3(0.5, 0.5, 0.5),
},
cubeModel);
cubeModel);

obb3.AddBehaviour<MovingRotating>();

auto cat = engine->NewObject();
cat.AddModel(*model);
auto &t = cat.AddTransform(Vec3(0.f, -5.f, -8.f), Vec3(0.1f), Mat4(1.0));
// auto cat = engine->NewObject();
// cat.AddModel(*model);
// auto &t = cat.AddTransform(Vec3(0.f, -5.f, -8.f), Vec3(0.1f), Mat4(1.0));


auto staticAABB = setUpObjRigidBody(
Expand Down