Clean up the code to be not everything in hpp files.
This commit is contained in:
parent
a1c8208b47
commit
6d21b7f163
6 changed files with 308 additions and 264 deletions
|
|
@ -1 +1,84 @@
|
||||||
#include "animation.hpp"
|
#include "animation.hpp"
|
||||||
|
#include "model.hpp"
|
||||||
|
#include "assimp_glm_helpers.hpp"
|
||||||
|
|
||||||
|
Animation::Animation(const std::string& animationPath, Model *model) {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
|
||||||
|
const aiScene* scene = importer.ReadFile(animationPath, aiProcess_Triangulate);
|
||||||
|
dbc::check(scene != nullptr, $F("Scene for animation {} failed to load.", animationPath));
|
||||||
|
dbc::check(scene->mRootNode, $F("Scene {} doesn't have a root node.", animationPath));
|
||||||
|
|
||||||
|
auto animation = scene->mAnimations[0];
|
||||||
|
$duration = animation->mDuration;
|
||||||
|
$ticks_per_sec = animation->mTicksPerSecond;
|
||||||
|
aiMatrix4x4 globalTransformation = scene->mRootNode->mTransformation;
|
||||||
|
globalTransformation = globalTransformation.Inverse();
|
||||||
|
ReadHierarchyData($root_node, scene->mRootNode);
|
||||||
|
ReadMissingBones(animation, *model);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bone* Animation::FindBone(const std::string& name) {
|
||||||
|
auto iter = std::find_if($bones.begin(), $bones.end(),
|
||||||
|
[&](const auto& bone) {
|
||||||
|
return bone.GetBoneName() == name;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return iter == $bones.end() ? nullptr : &(*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Animation::GetTicksPerSecond() {
|
||||||
|
return $ticks_per_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Animation::GetDuration() {
|
||||||
|
return $duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AssimpNodeData& Animation::GetRootNode() {
|
||||||
|
return $root_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, BoneInfo>& Animation::GetBoneIDMap()
|
||||||
|
{
|
||||||
|
return $bone_info_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::ReadMissingBones(const aiAnimation* animation, Model& model) {
|
||||||
|
// this code is weird as hell
|
||||||
|
int size = animation->mNumChannels;
|
||||||
|
auto& boneInfoMap = model.bone_info_map;
|
||||||
|
int& boneCount = model.bone_counter;
|
||||||
|
|
||||||
|
for(int i = 0; i < size; i++) {
|
||||||
|
auto channel = animation->mChannels[i];
|
||||||
|
std::string boneName = channel->mNodeName.data;
|
||||||
|
|
||||||
|
if(!boneInfoMap.contains(boneName)) {
|
||||||
|
boneInfoMap[boneName].id = boneCount;
|
||||||
|
boneCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbc::check(boneCount < MAX_BONES, "Too many bones!");
|
||||||
|
|
||||||
|
$bones.emplace_back(boneName,
|
||||||
|
boneInfoMap[boneName].id, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
$bone_info_map = boneInfoMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::ReadHierarchyData(AssimpNodeData& dest, const aiNode* src) {
|
||||||
|
dbc::check(src != nullptr, "aiNode src is null?!");
|
||||||
|
|
||||||
|
dest.name = src->mName.data;
|
||||||
|
dest.transformation = AssimpGLMHelpers::ConvertMatrixToGLMFormat(src->mTransformation);
|
||||||
|
dest.children_count = src->mNumChildren;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < src->mNumChildren; i++) {
|
||||||
|
AssimpNodeData newData;
|
||||||
|
ReadHierarchyData(newData, src->mChildren[i]);
|
||||||
|
dest.children.push_back(newData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "animdata.hpp"
|
#include "animdata.hpp"
|
||||||
#include "bone.hpp"
|
#include "bone.hpp"
|
||||||
#include "model.hpp"
|
|
||||||
#include "assimp_glm_helpers.hpp"
|
|
||||||
|
|
||||||
struct Bone;
|
struct Bone;
|
||||||
|
|
||||||
|
|
@ -28,88 +26,21 @@ struct Animation {
|
||||||
|
|
||||||
Animation() = default;
|
Animation() = default;
|
||||||
|
|
||||||
Animation(const std::string& animationPath, Model *model) {
|
Animation(const std::string& animationPath, Model *model);
|
||||||
Assimp::Importer importer;
|
|
||||||
|
|
||||||
const aiScene* scene = importer.ReadFile(animationPath, aiProcess_Triangulate);
|
~Animation() {}
|
||||||
dbc::check(scene != nullptr, $F("Scene for animation {} failed to load.", animationPath));
|
|
||||||
dbc::check(scene->mRootNode, $F("Scene {} doesn't have a root node.", animationPath));
|
|
||||||
|
|
||||||
auto animation = scene->mAnimations[0];
|
Bone* FindBone(const std::string& name);
|
||||||
$duration = animation->mDuration;
|
|
||||||
$ticks_per_sec = animation->mTicksPerSecond;
|
|
||||||
aiMatrix4x4 globalTransformation = scene->mRootNode->mTransformation;
|
|
||||||
globalTransformation = globalTransformation.Inverse();
|
|
||||||
ReadHierarchyData($root_node, scene->mRootNode);
|
|
||||||
ReadMissingBones(animation, *model);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Animation() {
|
float GetTicksPerSecond();
|
||||||
}
|
|
||||||
|
|
||||||
|
float GetDuration();
|
||||||
|
|
||||||
Bone* FindBone(const std::string& name) {
|
const AssimpNodeData& GetRootNode();
|
||||||
auto iter = std::find_if($bones.begin(), $bones.end(),
|
|
||||||
[&](const auto& bone) {
|
|
||||||
return bone.GetBoneName() == name;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return iter == $bones.end() ? nullptr : &(*iter);
|
const std::unordered_map<std::string, BoneInfo>& GetBoneIDMap();
|
||||||
}
|
|
||||||
|
|
||||||
float GetTicksPerSecond() {
|
void ReadMissingBones(const aiAnimation* animation, Model& model);
|
||||||
return $ticks_per_sec;
|
|
||||||
}
|
|
||||||
|
|
||||||
float GetDuration() {
|
void ReadHierarchyData(AssimpNodeData& dest, const aiNode* src);
|
||||||
return $duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AssimpNodeData& GetRootNode() {
|
|
||||||
return $root_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::unordered_map<std::string, BoneInfo>& GetBoneIDMap()
|
|
||||||
{
|
|
||||||
return $bone_info_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadMissingBones(const aiAnimation* animation, Model& model) {
|
|
||||||
// this code is weird as hell
|
|
||||||
int size = animation->mNumChannels;
|
|
||||||
auto& boneInfoMap = model.bone_info_map;
|
|
||||||
int& boneCount = model.bone_counter;
|
|
||||||
|
|
||||||
for(int i = 0; i < size; i++) {
|
|
||||||
auto channel = animation->mChannels[i];
|
|
||||||
std::string boneName = channel->mNodeName.data;
|
|
||||||
|
|
||||||
if(!boneInfoMap.contains(boneName)) {
|
|
||||||
boneInfoMap[boneName].id = boneCount;
|
|
||||||
boneCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbc::check(boneCount < MAX_BONES, "Too many bones!");
|
|
||||||
|
|
||||||
$bones.emplace_back(boneName,
|
|
||||||
boneInfoMap[boneName].id, channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
$bone_info_map = boneInfoMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadHierarchyData(AssimpNodeData& dest, const aiNode* src) {
|
|
||||||
dbc::check(src != nullptr, "aiNode src is null?!");
|
|
||||||
|
|
||||||
dest.name = src->mName.data;
|
|
||||||
dest.transformation = AssimpGLMHelpers::ConvertMatrixToGLMFormat(src->mTransformation);
|
|
||||||
dest.children_count = src->mNumChildren;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < src->mNumChildren; i++) {
|
|
||||||
AssimpNodeData newData;
|
|
||||||
ReadHierarchyData(newData, src->mChildren[i]);
|
|
||||||
dest.children.push_back(newData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1 +1,57 @@
|
||||||
#include "animator.hpp"
|
#include "animator.hpp"
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
#include <assimp/Importer.hpp>
|
||||||
|
#include "bone.hpp"
|
||||||
|
|
||||||
|
Animator::Animator(Animation* animation) :
|
||||||
|
$current_animation(animation)
|
||||||
|
{
|
||||||
|
$final_bone_matrices.reserve(MAX_BONES);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < MAX_BONES; i++) {
|
||||||
|
$final_bone_matrices.push_back(glm::mat4(1.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animator::UpdateAnimation(float current_time) {
|
||||||
|
if($current_animation) {
|
||||||
|
$current_time = $current_animation->GetTicksPerSecond() * current_time;
|
||||||
|
$current_time = fmod($current_time, $current_animation->GetDuration());
|
||||||
|
CalculateBoneTransform(&$current_animation->GetRootNode(), glm::mat4(1.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animator::PlayAnimation(Animation* animation) {
|
||||||
|
$current_animation = animation;
|
||||||
|
$current_time = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animator::CalculateBoneTransform(const AssimpNodeData* node, glm::mat4 parentTransform) {
|
||||||
|
std::string node_name = node->name;
|
||||||
|
glm::mat4 node_transform = node->transformation;
|
||||||
|
|
||||||
|
Bone *bone = $current_animation->FindBone(node_name);
|
||||||
|
|
||||||
|
if(bone) {
|
||||||
|
bone->Update($current_time);
|
||||||
|
node_transform = bone->GetLocalTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 global_transformation = parentTransform * node_transform;
|
||||||
|
|
||||||
|
auto bone_map = $current_animation->GetBoneIDMap();
|
||||||
|
|
||||||
|
if(bone_map.contains(node_name)) {
|
||||||
|
auto& bone_info = bone_map[node_name];
|
||||||
|
|
||||||
|
$final_bone_matrices[bone_info.id] = global_transformation * bone_info.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < node->children_count; i++) {
|
||||||
|
CalculateBoneTransform(&node->children[i], global_transformation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<glm::mat4>& Animator::GetFinalBoneMatrices() {
|
||||||
|
return $final_bone_matrices;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,72 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <assimp/scene.h>
|
|
||||||
#include <assimp/Importer.hpp>
|
|
||||||
#include "animation.hpp"
|
#include "animation.hpp"
|
||||||
#include "bone.hpp"
|
|
||||||
|
|
||||||
struct Bone;
|
|
||||||
|
|
||||||
struct Animator {
|
struct Animator {
|
||||||
std::vector<glm::mat4> $final_bone_matrices;
|
std::vector<glm::mat4> $final_bone_matrices;
|
||||||
Animation* $current_animation = nullptr;
|
Animation* $current_animation = nullptr;
|
||||||
float $current_time = 0.0f;
|
float $current_time = 0.0f;
|
||||||
|
|
||||||
Animator(Animation* animation) :
|
Animator(Animation* animation);
|
||||||
$current_animation(animation)
|
|
||||||
{
|
|
||||||
$final_bone_matrices.reserve(MAX_BONES);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < MAX_BONES; i++) {
|
void UpdateAnimation(float current_time);
|
||||||
$final_bone_matrices.push_back(glm::mat4(1.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAnimation(float current_time) {
|
void PlayAnimation(Animation* animation);
|
||||||
if($current_animation) {
|
|
||||||
$current_time = $current_animation->GetTicksPerSecond() * current_time;
|
|
||||||
$current_time = fmod($current_time, $current_animation->GetDuration());
|
|
||||||
CalculateBoneTransform(&$current_animation->GetRootNode(), glm::mat4(1.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayAnimation(Animation* animation) {
|
void CalculateBoneTransform(const AssimpNodeData* node, glm::mat4 parentTransform);
|
||||||
$current_animation = animation;
|
|
||||||
$current_time = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CalculateBoneTransform(const AssimpNodeData* node, glm::mat4 parentTransform) {
|
|
||||||
std::string node_name = node->name;
|
|
||||||
glm::mat4 node_transform = node->transformation;
|
|
||||||
|
|
||||||
Bone *bone = $current_animation->FindBone(node_name);
|
|
||||||
|
|
||||||
if(bone) {
|
|
||||||
bone->Update($current_time);
|
|
||||||
node_transform = bone->GetLocalTransform();
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 global_transformation = parentTransform * node_transform;
|
|
||||||
|
|
||||||
auto bone_map = $current_animation->GetBoneIDMap();
|
|
||||||
|
|
||||||
if(bone_map.contains(node_name)) {
|
|
||||||
auto& bone_info = bone_map[node_name];
|
|
||||||
|
|
||||||
$final_bone_matrices[bone_info.id] = global_transformation * bone_info.offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < node->children_count; i++) {
|
|
||||||
CalculateBoneTransform(&node->children[i], global_transformation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<glm::mat4>& GetFinalBoneMatrices() {
|
|
||||||
return $final_bone_matrices;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
std::vector<glm::mat4>& GetFinalBoneMatrices();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1 +1,144 @@
|
||||||
#include "bone.hpp"
|
#include "bone.hpp"
|
||||||
|
#include "assimp_glm_helpers.hpp"
|
||||||
|
|
||||||
|
Bone::Bone(const std::string& name, int ID, const aiNodeAnim* channel) :
|
||||||
|
$name(name),
|
||||||
|
$id(ID)
|
||||||
|
{
|
||||||
|
$num_positions = channel->mNumPositionKeys;
|
||||||
|
|
||||||
|
for(size_t pos_i = 0; pos_i < $num_positions; pos_i++) {
|
||||||
|
const auto& ai_position = channel->mPositionKeys[pos_i];
|
||||||
|
auto position = AssimpGLMHelpers::GetGLMVec(ai_position.mValue);
|
||||||
|
$positions.emplace_back(position, ai_position.mTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
$num_rotations = channel->mNumRotationKeys;
|
||||||
|
for(size_t rot_i = 0; rot_i < $num_rotations; rot_i++) {
|
||||||
|
const auto& ai_orientation = channel->mRotationKeys[rot_i];
|
||||||
|
auto orientation = AssimpGLMHelpers::GetGLMQuat(ai_orientation.mValue);
|
||||||
|
|
||||||
|
$rotations.emplace_back(orientation, ai_orientation.mTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
$num_scalings = channel->mNumScalingKeys;
|
||||||
|
for(size_t key_i = 0; key_i < $num_scalings; key_i++) {
|
||||||
|
const auto& ai_scale = channel->mScalingKeys[key_i];
|
||||||
|
auto scale = AssimpGLMHelpers::GetGLMVec(ai_scale.mValue);
|
||||||
|
$scales.emplace_back(scale, ai_scale.mTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bone::Update(float animationTime) {
|
||||||
|
glm::mat4 translation = InterpolatPosition(animationTime);
|
||||||
|
glm::mat4 rotation = InterpolateRotation(animationTime);
|
||||||
|
glm::mat4 scale = InterpolateScaling(animationTime);
|
||||||
|
$local_transform = translation * rotation * scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 Bone::GetLocalTransform() {
|
||||||
|
return $local_transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Bone::GetBoneName() const {
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Bone::GetBoneId() {
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Bone::GetPositionIndex(float animationTime) {
|
||||||
|
for(size_t index = 0; index < $num_positions - 1; ++index) {
|
||||||
|
auto ts = $positions[index + 1].timeStamp;
|
||||||
|
|
||||||
|
if(animationTime < ts) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbc::sentinel("Failed to find an animation position");
|
||||||
|
}
|
||||||
|
|
||||||
|
int Bone::GetRotationIndex(float animationTime) {
|
||||||
|
for(size_t index = 0; index < $num_rotations - 1; ++index) {
|
||||||
|
auto ts = $rotations[index + 1].timeStamp;
|
||||||
|
|
||||||
|
if(animationTime < ts) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbc::sentinel("Failed to find an animation rotation");
|
||||||
|
}
|
||||||
|
|
||||||
|
int Bone::GetScaleIndex(float animationTime) {
|
||||||
|
for(size_t index = 0; index < $num_scalings - 1; ++index) {
|
||||||
|
auto ts = $scales[index + 1].timeStamp;
|
||||||
|
if(animationTime < ts) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbc::sentinel("Failed to find an animation scale");
|
||||||
|
}
|
||||||
|
|
||||||
|
float Bone::GetScaleFactor(float lastTimeStamp, float nextTimeStamp, float animationTime) {
|
||||||
|
float scaleFactor = 0.0f;
|
||||||
|
float midWayLength = animationTime - lastTimeStamp;
|
||||||
|
float framesDiff = nextTimeStamp - lastTimeStamp;
|
||||||
|
scaleFactor = midWayLength / framesDiff;
|
||||||
|
return scaleFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 Bone::InterpolatPosition(float animationTime) {
|
||||||
|
if($num_positions == 1) {
|
||||||
|
return glm::translate(glm::mat4(1.0f), $positions[0].position);
|
||||||
|
}
|
||||||
|
|
||||||
|
int p0Index = GetPositionIndex(animationTime);
|
||||||
|
auto& p0 = $positions[p0Index];
|
||||||
|
auto& p1 = $positions[p0Index + 1];
|
||||||
|
|
||||||
|
float scaleFactor = GetScaleFactor(
|
||||||
|
p0.timeStamp, p1.timeStamp, animationTime);
|
||||||
|
|
||||||
|
glm::vec3 finalPosition = glm::mix(p0.position,
|
||||||
|
p1.position, scaleFactor);
|
||||||
|
|
||||||
|
return glm::translate(glm::mat4(1.0f), finalPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 Bone::InterpolateRotation(float animationTime) {
|
||||||
|
if($num_rotations == 1) {
|
||||||
|
auto rotation = glm::normalize($rotations[0].orientation);
|
||||||
|
return glm::toMat4(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
int p0Index = GetRotationIndex(animationTime);
|
||||||
|
auto& p0 = $rotations[p0Index];
|
||||||
|
auto& p1 = $rotations[p0Index + 1];
|
||||||
|
|
||||||
|
float scaleFactor = GetScaleFactor(
|
||||||
|
p0.timeStamp, p1.timeStamp, animationTime);
|
||||||
|
|
||||||
|
glm::quat finalRotation = glm::slerp(
|
||||||
|
p0.orientation, p1.orientation, scaleFactor);
|
||||||
|
|
||||||
|
return glm::toMat4(finalRotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 Bone::InterpolateScaling(float animationTime) {
|
||||||
|
if($num_scalings == 1) {
|
||||||
|
return glm::scale(glm::mat4(1.0f), $scales[0].scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
int p0Index = GetScaleIndex(animationTime);
|
||||||
|
|
||||||
|
auto& p0 = $scales[p0Index];
|
||||||
|
auto& p1 = $scales[p0Index + 1];
|
||||||
|
float scaleFactor = GetScaleFactor(
|
||||||
|
p0.timeStamp, p1.timeStamp, animationTime);
|
||||||
|
|
||||||
|
glm::vec3 finalScale = glm::mix(p0.scale, p1.scale, scaleFactor);
|
||||||
|
|
||||||
|
return glm::scale(glm::mat4(1.0f), finalScale);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#define GLM_ENABLE_EXPERIMENTAL
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
#include "assimp_glm_helpers.hpp"
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct KeyPosition {
|
struct KeyPosition {
|
||||||
|
|
@ -40,145 +39,27 @@ struct Bone
|
||||||
std::string $name{};
|
std::string $name{};
|
||||||
int $id = 0;
|
int $id = 0;
|
||||||
|
|
||||||
Bone(const std::string& name, int ID, const aiNodeAnim* channel) :
|
Bone(const std::string& name, int ID, const aiNodeAnim* channel);
|
||||||
$name(name),
|
|
||||||
$id(ID)
|
|
||||||
{
|
|
||||||
$num_positions = channel->mNumPositionKeys;
|
|
||||||
|
|
||||||
for(size_t pos_i = 0; pos_i < $num_positions; pos_i++) {
|
void Update(float animationTime);
|
||||||
const auto& ai_position = channel->mPositionKeys[pos_i];
|
|
||||||
auto position = AssimpGLMHelpers::GetGLMVec(ai_position.mValue);
|
|
||||||
$positions.emplace_back(position, ai_position.mTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
$num_rotations = channel->mNumRotationKeys;
|
glm::mat4 GetLocalTransform();
|
||||||
for(size_t rot_i = 0; rot_i < $num_rotations; rot_i++) {
|
|
||||||
const auto& ai_orientation = channel->mRotationKeys[rot_i];
|
|
||||||
auto orientation = AssimpGLMHelpers::GetGLMQuat(ai_orientation.mValue);
|
|
||||||
|
|
||||||
$rotations.emplace_back(orientation, ai_orientation.mTime);
|
std::string GetBoneName() const;
|
||||||
}
|
|
||||||
|
|
||||||
$num_scalings = channel->mNumScalingKeys;
|
int GetBoneId();
|
||||||
for(size_t key_i = 0; key_i < $num_scalings; key_i++) {
|
|
||||||
const auto& ai_scale = channel->mScalingKeys[key_i];
|
|
||||||
auto scale = AssimpGLMHelpers::GetGLMVec(ai_scale.mValue);
|
|
||||||
$scales.emplace_back(scale, ai_scale.mTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Update(float animationTime) {
|
int GetPositionIndex(float animationTime);
|
||||||
glm::mat4 translation = InterpolatPosition(animationTime);
|
|
||||||
glm::mat4 rotation = InterpolateRotation(animationTime);
|
|
||||||
glm::mat4 scale = InterpolateScaling(animationTime);
|
|
||||||
$local_transform = translation * rotation * scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 GetLocalTransform() {
|
int GetRotationIndex(float animationTime);
|
||||||
return $local_transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetBoneName() const {
|
int GetScaleIndex(float animationTime);
|
||||||
return $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetBoneId() {
|
float GetScaleFactor(float lastTimeStamp, float nextTimeStamp, float animationTime);
|
||||||
return $id;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetPositionIndex(float animationTime) {
|
glm::mat4 InterpolatPosition(float animationTime);
|
||||||
for(size_t index = 0; index < $num_positions - 1; ++index) {
|
|
||||||
auto ts = $positions[index + 1].timeStamp;
|
|
||||||
|
|
||||||
if(animationTime < ts) {
|
glm::mat4 InterpolateRotation(float animationTime);
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dbc::sentinel("Failed to find an animation position");
|
glm::mat4 InterpolateScaling(float animationTime);
|
||||||
}
|
|
||||||
|
|
||||||
int GetRotationIndex(float animationTime) {
|
|
||||||
for(size_t index = 0; index < $num_rotations - 1; ++index) {
|
|
||||||
auto ts = $rotations[index + 1].timeStamp;
|
|
||||||
|
|
||||||
if(animationTime < ts) {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dbc::sentinel("Failed to find an animation rotation");
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetScaleIndex(float animationTime) {
|
|
||||||
for(size_t index = 0; index < $num_scalings - 1; ++index) {
|
|
||||||
auto ts = $scales[index + 1].timeStamp;
|
|
||||||
if(animationTime < ts) {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dbc::sentinel("Failed to find an animation scale");
|
|
||||||
}
|
|
||||||
|
|
||||||
float GetScaleFactor(float lastTimeStamp, float nextTimeStamp, float animationTime) {
|
|
||||||
float scaleFactor = 0.0f;
|
|
||||||
float midWayLength = animationTime - lastTimeStamp;
|
|
||||||
float framesDiff = nextTimeStamp - lastTimeStamp;
|
|
||||||
scaleFactor = midWayLength / framesDiff;
|
|
||||||
return scaleFactor;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 InterpolatPosition(float animationTime) {
|
|
||||||
if($num_positions == 1) {
|
|
||||||
return glm::translate(glm::mat4(1.0f), $positions[0].position);
|
|
||||||
}
|
|
||||||
|
|
||||||
int p0Index = GetPositionIndex(animationTime);
|
|
||||||
auto& p0 = $positions[p0Index];
|
|
||||||
auto& p1 = $positions[p0Index + 1];
|
|
||||||
|
|
||||||
float scaleFactor = GetScaleFactor(
|
|
||||||
p0.timeStamp, p1.timeStamp, animationTime);
|
|
||||||
|
|
||||||
glm::vec3 finalPosition = glm::mix(p0.position,
|
|
||||||
p1.position, scaleFactor);
|
|
||||||
|
|
||||||
return glm::translate(glm::mat4(1.0f), finalPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 InterpolateRotation(float animationTime) {
|
|
||||||
if($num_rotations == 1) {
|
|
||||||
auto rotation = glm::normalize($rotations[0].orientation);
|
|
||||||
return glm::toMat4(rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
int p0Index = GetRotationIndex(animationTime);
|
|
||||||
auto& p0 = $rotations[p0Index];
|
|
||||||
auto& p1 = $rotations[p0Index + 1];
|
|
||||||
|
|
||||||
float scaleFactor = GetScaleFactor(
|
|
||||||
p0.timeStamp, p1.timeStamp, animationTime);
|
|
||||||
|
|
||||||
glm::quat finalRotation = glm::slerp(
|
|
||||||
p0.orientation, p1.orientation, scaleFactor);
|
|
||||||
|
|
||||||
return glm::toMat4(finalRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 InterpolateScaling(float animationTime) {
|
|
||||||
if($num_scalings == 1) {
|
|
||||||
return glm::scale(glm::mat4(1.0f), $scales[0].scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
int p0Index = GetScaleIndex(animationTime);
|
|
||||||
|
|
||||||
auto& p0 = $scales[p0Index];
|
|
||||||
auto& p1 = $scales[p0Index + 1];
|
|
||||||
float scaleFactor = GetScaleFactor(
|
|
||||||
p0.timeStamp, p1.timeStamp, animationTime);
|
|
||||||
|
|
||||||
glm::vec3 finalScale = glm::mix(p0.scale, p1.scale, scaleFactor);
|
|
||||||
|
|
||||||
return glm::scale(glm::mat4(1.0f), finalScale);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue