Fixed memory leaks and cleaned up Skeleton and BlendTree

This commit is contained in:
viktorljung
2016-02-25 11:30:09 +01:00
parent 606a9bf94f
commit c97d0d9381
10 changed files with 606 additions and 545 deletions
+46 -307
View File
@@ -1,55 +1,6 @@
#include "Rendering/Skeleton.h"
int Skeleton::CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix)
{
if (m_BonesByName.find(name) != m_BonesByName.end()) {
return m_BonesByName.at(name)->ID;
} else {
Bone* bone;
if (parentID == -1) {
bone = new Bone(ID, nullptr, name, offsetMatrix);
RootBone = bone;
} else {
Bone* parent = Bones[parentID];
bone = new Bone(ID, parent, name, offsetMatrix);
parent->Children.push_back(bone);
}
Bones[ID] = bone;
m_BonesByName[name] = bone;
return ID;
}
}
Skeleton::~Skeleton()
{
for (auto &kv : Bones) {
delete kv.second;
}
}
const Skeleton::Animation* Skeleton::GetAnimation(std::string name)
{
auto it = Animations.find(name);
if (it != Animations.end()) {
return const_cast<const Animation*>(&it->second);
} else {
return nullptr;
}
}
std::vector<glm::mat4> Skeleton::GetFrameBones()
{
std::vector<glm::mat4> finalMatrices;
for (auto& b : Bones) {
finalMatrices.push_back(glm::mat4(1));
}
return finalMatrices;
}
std::map<int, glm::mat4> Skeleton::GetFrameBones(const Animation* animation, const double time, bool additive, bool noRootMotion /*= false*/)
std::map<int, glm::mat4> Skeleton::GetFrameBones(const Animation* animation, double time, bool additive, bool noRootMotion /*= false*/)
{
if (animation == nullptr) {
std::map<int, glm::mat4> finalMatrices;
@@ -63,7 +14,7 @@ std::map<int, glm::mat4> Skeleton::GetFrameBones(const Animation* animation, con
std::map<int, glm::mat4> frameBones;
if(!additive) {
AccumulateBoneTransforms(true, animation, time, frameBones, additive, RootBone, glm::mat4(1));
AccumulateBoneTransforms(true, animation, time, frameBones, RootBone, glm::mat4(1));
} else {
AdditiveBoneTransforms(animation, time, frameBones, RootBone);
}
@@ -71,12 +22,8 @@ std::map<int, glm::mat4> Skeleton::GetFrameBones(const Animation* animation, con
return frameBones;
}
void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map<int, glm::mat4>& boneMatrices, bool additive, const Bone* bone, glm::mat4 parentMatrix)
void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map<int, glm::mat4>& boneMatrices, const Bone* bone, glm::mat4 parentMatrix)
{
if (additive) {
time += 1.0/60.0; // first frame is a reference frame
}
glm::mat4 boneMatrix;
@@ -138,7 +85,7 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim
}
for (auto &child : bone->Children) {
AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, additive, child, boneMatrix);
AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, child, boneMatrix);
}
}
@@ -157,20 +104,6 @@ void Skeleton::AdditiveBoneTransforms(const Animation* animation, double time, s
}
}
glm::mat4 Skeleton::AdditiveBlend(const Bone* bone, AnimationOffset animationOffset, glm::mat4 targetPose)
{
/*
AnimationOffset refOffset = animationOffset;
refOffset.time = 0.5f; // reference pose is at 0.5s for now
glm::mat4 refPose = GetAdditiveBonePose(bone, refOffset);
glm::mat4 srcPose = GetAdditiveBonePose(bone, animationOffset);
glm::mat4 differencePose = srcPose * glm::inverse(refPose);
glm::mat4 finalPose = differencePose * targetPose;*/
return glm::mat4();
}
glm::mat4 Skeleton::GetAdditiveBonePose(const Bone* bone, const Animation* animation, double time)
{
glm::vec3 position = glm::vec3(0);
@@ -227,9 +160,6 @@ glm::mat4 Skeleton::GetBonePose(const Bone* bone, const Animation* animation, do
{
glm::mat4 boneMatrix;
std::vector<JointFramePose> JointPoses;
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
@@ -346,235 +276,7 @@ glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animatio
}
}
glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector<AnimationData> animations, AnimationOffset animationOffset, glm::mat4 childMatrix)
{
glm::mat4 boneMatrix;
std::vector<JointFramePose> JointPoses;
for (const AnimationData animationData : animations) {
const Animation* animation = animationData.animation;
const float time = animationData.time;
JointFramePose jointPose;
jointPose.Weight = animationData.weight;;
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
Animation::Keyframe currentFrame;
Animation::Keyframe nextFrame;
if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone
for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame
if (time >= boneKeyFrames.at(index).Time) {
currentFrame = boneKeyFrames.at(index);
nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size());
break;
}
}
float progress;
if (nextFrame.Index == 0) {
nextFrame = currentFrame;
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
} else {
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
}
if (progress > 1.0f || progress < 0.0f) {
progress = glm::clamp(progress, 0.0f, 1.0f);
}
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
glm::vec3 position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
glm::quat rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
glm::vec3 scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
// Flag for no root motion
if (bone == RootBone && noRootMotion) {
position.x = 0;
position.z = 0;
}
jointPose.Pose = (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale));
JointPoses.push_back(jointPose);
} else { // 1 keyframes for the current bone
currentFrame = boneKeyFrames.at(0);
jointPose.Pose = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale));
JointPoses.push_back(jointPose);
}
} else { // 0 keyframes for the current bone
}
}
if (JointPoses.size() == 0) {
if (bone->Parent) {
glm::mat4 jointPose = (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix);
glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, jointPose);
boneMatrix = boneTransform * childMatrix;
} else {
boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix;
}
} else {
float totalWeight = 0;
for (JointFramePose jointFramePose : JointPoses) {
totalWeight += jointFramePose.Weight;
}
glm::mat4 finalBlend = glm::mat4(0);
for (JointFramePose jointFramePose : JointPoses) {
if (jointFramePose.Weight == 1.0f) {
finalBlend = jointFramePose.Pose;
} else {
finalBlend += jointFramePose.Pose * (jointFramePose.Weight / totalWeight);
}
}
glm::mat4 boneTransform = AdditiveBlend(bone, animationOffset, finalBlend);
boneMatrix = boneTransform * childMatrix;
}
if (bone->Parent != nullptr) {
return GetBoneTransform(noRootMotion, bone->Parent, animations, animationOffset, boneMatrix);
} else {
return boneMatrix;
}
}
glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector<AnimationData> animations, glm::mat4 childMatrix)
{
glm::mat4 boneMatrix;
/* std::vector<JointFrameTransform> JointTransforms;
for (const AnimationData animationData : animations) {
const Animation* animation = animationData.animation;
const float time = animationData.time;
JointFrameTransform jointTransform;
jointTransform.Weight = animationData.weight;;
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
Animation::Keyframe currentFrame;
Animation::Keyframe nextFrame;
if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone
for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame
if (time >= boneKeyFrames.at(index).Time) {
currentFrame = boneKeyFrames.at(index);
nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size());
break;
}
}
float progress;
if (nextFrame.Index == 0) {
nextFrame = currentFrame;
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
} else {
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
}
if (progress > 1.0f || progress < 0.0f) {
progress = glm::clamp(progress, 0.0f, 1.0f);
}
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
jointTransform.Position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
jointTransform.Rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
jointTransform.Scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
// Flag for no root motion
if (bone == RootBone && noRootMotion) {
jointTransform.Position.x = 0;
jointTransform.Position.z = 0;
}
JointTransforms.push_back(jointTransform);
} else { // 1 keyframes for the current bone
currentFrame = boneKeyFrames.at(0);
jointTransform.Position = currentFrame.BoneProperties.Position;
jointTransform.Rotation = currentFrame.BoneProperties.Rotation;
jointTransform.Scale = currentFrame.BoneProperties.Scale;
JointTransforms.push_back(jointTransform);
}
} else { // 0 keyframes for the current bone
}
}
if (JointTransforms.size() <= 0) {
if (bone->Parent) {
boneMatrix = glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix * childMatrix;
} else {
boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix;
}
} else if (JointTransforms.size() == 1) {
boneMatrix = (glm::translate(JointTransforms.at(0).Position) * glm::toMat4(JointTransforms.at(0).Rotation) * glm::scale(JointTransforms.at(0).Scale)) * childMatrix;
} else {
glm::vec3 finalPosInterp;
glm::quat finalRotInterp;
glm::vec3 finalScaleInterp;
float totalWeight = 0;
for (JointFrameTransform jointTransform : JointTransforms) {
totalWeight += jointTransform.Weight;
}
for (JointFrameTransform jointTransform : JointTransforms) {
if (jointTransform.Weight == 1.0f) {
finalPosInterp = jointTransform.Position;
finalRotInterp = jointTransform.Rotation;
finalScaleInterp = jointTransform.Scale;
break;
} else {
finalPosInterp += jointTransform.Position * (jointTransform.Weight/totalWeight);
finalRotInterp *= glm::slerp(glm::quat(), jointTransform.Rotation, (jointTransform.Weight/totalWeight));
finalScaleInterp += jointTransform.Scale * (jointTransform.Weight/totalWeight);
}
}
boneMatrix = (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) * childMatrix;
}
if (bone->Parent != nullptr) {
return GetBoneTransform(noRootMotion, bone->Parent, animations, boneMatrix);
} else {
return boneMatrix;
}*/
return boneMatrix;
}
std::map<int, glm::mat4> Skeleton::BlendPoses(std::map<int, glm::mat4> pose1, std::map<int, glm::mat4> pose2, float weight)
std::map<int, glm::mat4> Skeleton::BlendPoses(const std::map<int, glm::mat4>& pose1, const std::map<int, glm::mat4>& pose2, float weight)
{
std::map<int, glm::mat4> finalPose;
@@ -596,8 +298,7 @@ std::map<int, glm::mat4> Skeleton::BlendPoses(std::map<int, glm::mat4> pose1, st
return finalPose;
}
std::map<int, glm::mat4> Skeleton::OverridePose(std::map<int, glm::mat4> overridePose, std::map<int, glm::mat4> targetPose)
std::map<int, glm::mat4> Skeleton::OverridePose(const std::map<int, glm::mat4>& overridePose, const std::map<int, glm::mat4>& targetPose)
{
std::map<int, glm::mat4> finalPose;
@@ -612,8 +313,7 @@ std::map<int, glm::mat4> Skeleton::OverridePose(std::map<int, glm::mat4> overrid
return finalPose;
}
std::map<int, glm::mat4> Skeleton::BlendPoseAdditive(std::map<int, glm::mat4> additivePose, std::map<int, glm::mat4> targetPose)
std::map<int, glm::mat4> Skeleton::BlendPoseAdditive(const std::map<int, glm::mat4>& additivePose, const std::map<int, glm::mat4>& targetPose)
{
std::map<int, glm::mat4> finalPose;
@@ -683,3 +383,42 @@ int Skeleton::GetBoneID(std::string name)
return m_BonesByName.at(name)->ID;
}
}
int Skeleton::CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix)
{
if (m_BonesByName.find(name) != m_BonesByName.end()) {
return m_BonesByName.at(name)->ID;
} else {
Bone* bone;
if (parentID == -1) {
bone = new Bone(ID, nullptr, name, offsetMatrix);
RootBone = bone;
} else {
Bone* parent = Bones[parentID];
bone = new Bone(ID, parent, name, offsetMatrix);
parent->Children.push_back(bone);
}
Bones[ID] = bone;
m_BonesByName[name] = bone;
return ID;
}
}
Skeleton::~Skeleton()
{
for (auto &kv : Bones) {
delete kv.second;
}
}
const Skeleton::Animation* Skeleton::GetAnimation(std::string name)
{
auto it = Animations.find(name);
if (it != Animations.end()) {
return const_cast<const Animation*>(&it->second);
} else {
return nullptr;
}
}