Fixed BoneAttachment component

This commit is contained in:
viktorljung
2016-02-11 13:36:27 +01:00
parent 607150189c
commit 97de31be65
4 changed files with 294 additions and 25 deletions
+243
View File
@@ -448,6 +448,249 @@ 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<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) {
LOG_INFO("Progress: %f", progress);
progress = glm::clamp(progress, 0.0f, 1.0f);
}
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
// Flag for no root motion
if (bone == RootBone && noRootMotion) {
jointTransform.PositionInterp.x = 0;
jointTransform.PositionInterp.z = 0;
}
JointTransforms.push_back(jointTransform);
} else { // 1 keyframes for the current bone
currentFrame = boneKeyFrames.at(0);
jointTransform.PositionInterp = currentFrame.BoneProperties.Position;
jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation;
jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale;
JointTransforms.push_back(jointTransform);
}
} else { // 0 keyframes for the current bone
}
}
glm::mat4 offset = GetOffsetTransform(bone, animationOffset);
if (JointTransforms.size() == 0) {
if (bone->Parent) {
if (offset != glm::mat4(1)) {
boneMatrix = offset * childMatrix;// *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix));
} else {
boneMatrix = ((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)) * childMatrix;
}
} else {
boneMatrix = offset * glm::inverse(bone->OffsetMatrix);
}
} 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.PositionInterp;
finalRotInterp = jointTransform.RotationInterp;
finalScaleInterp = jointTransform.ScaleInterp;
break;
} else {
finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight);
finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight));
finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight);
}
}
if (offset != glm::mat4(1)) {
boneMatrix = ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset) * childMatrix;
} else {
boneMatrix = (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) * 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) {
LOG_INFO("Progress: %f", progress);
progress = glm::clamp(progress, 0.0f, 1.0f);
}
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
// Flag for no root motion
if (bone == RootBone && noRootMotion) {
jointTransform.PositionInterp.x = 0;
jointTransform.PositionInterp.z = 0;
}
JointTransforms.push_back(jointTransform);
} else { // 1 keyframes for the current bone
currentFrame = boneKeyFrames.at(0);
jointTransform.PositionInterp = currentFrame.BoneProperties.Position;
jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation;
jointTransform.ScaleInterp = 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).PositionInterp) * glm::toMat4(JointTransforms.at(0).RotationInterp) * glm::scale(JointTransforms.at(0).ScaleInterp)) * 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.PositionInterp;
finalRotInterp = jointTransform.RotationInterp;
finalScaleInterp = jointTransform.ScaleInterp;
break;
} else {
finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight);
finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight));
finalScaleInterp += jointTransform.ScaleInterp * (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;
}
}
int Skeleton::GetBoneID(std::string name)
{
if (m_BonesByName.find(name) == m_BonesByName.end()) {