AutoAnimationBlend on unique node working but scale is not working correctly

This commit is contained in:
viktorljung
2016-03-02 13:30:04 +01:00
parent 5bc0483f49
commit 07ccb9c041
13 changed files with 1404 additions and 749 deletions
+2 -2
View File
@@ -33,8 +33,8 @@ void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int
va_end(args);
if (logLevel == LOG_LEVEL_ERROR) {
std::cerr << file << ":" << line << " " << func << std::endl;
std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;
/*std::cerr << file << ":" << line << " " << func << std::endl;
std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;*/
} else {
std::cout << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;
}
+223 -4
View File
@@ -3,13 +3,21 @@
AnimationSystem::AnimationSystem(SystemParams params)
: System(params)
{
EVENT_SUBSCRIBE_MEMBER(m_EAnimationBlend, &AnimationSystem::OnAnimationBlend);
EVENT_SUBSCRIBE_MEMBER(m_EAutoAnimationBlend, &AnimationSystem::OnAutoAnimationBlend);
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &AnimationSystem::OnInputCommand);
}
void AnimationSystem::Update(double dt)
{
ImGui::InputText("AnimationName1", &m_AnimationName1[0], sizeof(m_AnimationName1));
ImGui::SliderFloat("Blendtime1", &m_BlendTime1, 0.f, 10.f);
ImGui::InputText("AnimationName2", &m_AnimationName2[0], sizeof(m_AnimationName2));
ImGui::SliderFloat("Blendtime2", &m_BlendTime2, 0.f, 10.f);
UpdateAnimations(dt);
CreateBlendTrees();
UpdateWeights(dt);
}
void AnimationSystem::CreateBlendTrees()
@@ -94,16 +102,17 @@ void AnimationSystem::UpdateAnimations(double dt)
e.Entity = entity;
e.Name = (std::string)animationC["AnimationName"];
m_EventBroker->Publish(e);
AnimationComplete(entity);
(double&)animationC["Speed"] = 0.0;
} else if (nextTime < 0) {
Events::AnimationComplete e;
e.Entity = entity;
e.Name = (std::string)animationC["AnimationName"];
m_EventBroker->Publish(e);
AnimationComplete(entity);
nextTime = 0;
(double&)animationC["Speed"] = 0.0;
}
(double&)animationC["Speed"] = 0.0;
} else {
if (nextTime > animation->Duration) {
Events::AnimationComplete e;
@@ -131,3 +140,213 @@ void AnimationSystem::UpdateAnimations(double dt)
}
}
void AnimationSystem::UpdateWeights(double dt)
{
/* for (auto it = m_BlendJobs.begin(); it != m_BlendJobs.end(); it++) {
if (!it->BlendEntity.Valid()) {
it = m_BlendJobs.erase(it);
continue;
}
if (it->BlendEntity.HasComponent("Blend")) {
it->CurrentTime += dt;
double progress = it->CurrentTime / it->Duration;
progress = glm::clamp(progress, 0.0, 1.0);
double weight = ((it->GoalWeight - it->StartWeight) * progress) + it->StartWeight;
(double&)it->BlendEntity["Blend"]["Weight"] = weight;
if(weight == it->GoalWeight) {
it = m_BlendJobs.erase(it);
}
}
}*/
for (auto it = m_AutoBlendJobs.begin(); it != m_AutoBlendJobs.end();) {
it->CurrentTime += dt;
if (!it->RootNode.Valid()) {
it = m_AutoBlendJobs.erase(it);
continue;
}
if (!it->RootNode.HasComponent("Model")) {
it = m_AutoBlendJobs.erase(it);
continue;
}
Model* model;
try {
model = ResourceManager::Load<::Model, true>(it->RootNode["Model"]["Resource"]);
} catch (const std::exception&) {
continue;
}
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
if (skeleton == nullptr) {
continue;
}
std::shared_ptr<BlendTree> blendTree;
if(skeleton->BlendTrees.find(it->RootNode) != skeleton->BlendTrees.end()) {
blendTree = skeleton->BlendTrees.at(it->RootNode);
} else {
it = m_AutoBlendJobs.erase(it);
continue;
}
it->BlendInfo.progress = glm::clamp(it->CurrentTime / it->Duration, 0.0, 1.0);
it->BlendInfo = blendTree->AutoBlendStep(it->BlendInfo);
if (it->CurrentTime >= it->Duration) {
it = m_AutoBlendJobs.erase(it);
continue;
}
++it;
}
}
void AnimationSystem::AnimationComplete(EntityWrapper animationEntity)
{
for (auto it = m_QueuedBlendJobs.begin(); it != m_QueuedBlendJobs.end(); it++) {
if (!it->BlendEntity.Valid() || !it->AnimationEntity.Valid()) {
it = m_QueuedBlendJobs.erase(it);
continue;
}
if(animationEntity == it->AnimationEntity) {
BlendJob bj;
bj.BlendEntity = it->BlendEntity;
bj.StartWeight = it->StartWeight;
bj.GoalWeight = it->GoalWeight;
bj.Duration = it->Duration;
bj.CurrentTime = 0.0;
m_BlendJobs.push_back(bj);
it = m_QueuedBlendJobs.erase(it);
}
}
}
bool AnimationSystem::OnAnimationBlend(Events::AnimationBlend& e)
{
if(!e.BlendEntity.Valid()) {
return false;
}
if(!e.BlendEntity.HasComponent("Blend")){
return false;
}
if (e.AnimationEntity.Valid()) {
if (e.AnimationEntity.HasComponent("Animation")) {
QueuedBlendJob qbj;
qbj.BlendEntity = e.BlendEntity;
qbj.StartWeight = (double)e.BlendEntity["Blend"]["Weight"];
qbj.GoalWeight = e.GoalWeight;
qbj.Duration = e.Duration;
qbj.CurrentTime = 0.0;
qbj.AnimationEntity = e.AnimationEntity;
m_QueuedBlendJobs.push_back(qbj);
return true;
}
}
BlendJob bj;
bj.BlendEntity = e.BlendEntity;
bj.StartWeight = (double)e.BlendEntity["Blend"]["Weight"];
bj.GoalWeight = e.GoalWeight;
bj.Duration = e.Duration;
bj.CurrentTime = 0.0;
m_BlendJobs.push_back(bj);
return true;
}
bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e)
{
if(!e.RootNode.Valid()) {
return false;
}
if(!e.RootNode.HasComponent("Model")) {
return false;
}
AutoBlendJob abj;
abj.RootNode = e.RootNode;
abj.CurrentTime = 0.0;
abj.Duration = e.Duration;
BlendTree::AutoBlendInfo abInfo;
abInfo.NodeName = e.NodeName;
abInfo.progress = 0.0;
abj.BlendInfo = abInfo;
m_AutoBlendJobs.push_back(abj);
}
bool AnimationSystem::OnInputCommand(const Events::InputCommand& e)
{
if (e.Value == 1.f) {
if (e.Command == "BlendTest0") {
auto blendComponents = m_World->GetComponents("BlendAdditive");
if (blendComponents == nullptr) {
return false;
}
for (auto& bc : *blendComponents) {
EntityWrapper entity = EntityWrapper(m_World, bc.EntityID);
if (entity.Name() == "Assault") {
Events::AutoAnimationBlend aeb;
aeb.Duration = m_BlendTime1;
aeb.NodeName = m_AnimationName1;
aeb.RootNode = entity;
m_EventBroker->Publish(aeb);
}
}
} else if (e.Command == "BlendTest1") {
auto blendComponents = m_World->GetComponents("BlendAdditive");
if (blendComponents == nullptr) {
return false;
}
for (auto& bc : *blendComponents) {
EntityWrapper entity = EntityWrapper(m_World, bc.EntityID);
if (entity.Name() == "Assault") {
Events::AutoAnimationBlend aeb;
aeb.Duration = m_BlendTime2;
aeb.NodeName = m_AnimationName2;
aeb.RootNode = entity;
m_EventBroker->Publish(aeb);
}
}
}
}
}
+82 -6
View File
@@ -14,6 +14,7 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton)
}
m_Root = new Node();
m_Root->Entity = ModelEntity;
m_Root->Name = ModelEntity.Name();
m_Root->Pose = m_Skeleton->GetFrameBones(animation, (double)ModelEntity["Animation"]["Time"], (bool)ModelEntity["Animation"]["Additive"]);
m_Root->Parent = nullptr;
@@ -21,15 +22,18 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton)
} else if (ModelEntity.HasComponent("Blend")) {
m_Root = new Node();
m_Root->Entity = ModelEntity;
m_Root->Name = ModelEntity.Name();
m_Root->Parent = nullptr;
m_Root->Type = NodeType::Blend;
m_Root->Weight = (double)ModelEntity["Blend"]["Weight"];
(double&)ModelEntity["Blend"]["Weight"] = glm::clamp((double)ModelEntity["Blend"]["Weight"], 0.0, 1.0);
m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["Blend"]["Pose1"], ModelEntity);
m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["Blend"]["Pose2"], ModelEntity);
} else if (ModelEntity.HasComponent("BlendOverride")) {
m_Root = new Node();
m_Root->Entity = ModelEntity;
m_Root->Name = ModelEntity.Name();
m_Root->Parent = nullptr;
m_Root->Type = NodeType::Override;
@@ -38,6 +42,7 @@ BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton)
} else if (ModelEntity.HasComponent("BlendAdditive")) {
m_Root = new Node();
m_Root->Entity = ModelEntity;
m_Root->Name = ModelEntity.Name();
m_Root->Parent = nullptr;
m_Root->Type = NodeType::Additive;
@@ -97,8 +102,6 @@ void BlendTree::PrintTree()
LOG_INFO("%s", currentNode->Name.c_str());
currentNode = currentNode->Next();
}
}
BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity)
@@ -116,6 +119,7 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E
}
Node* node = new Node();
node->Entity = childEntity;
node->Name = childEntity.Name();
node->Pose = m_Skeleton->GetFrameBones(animation, (double)childEntity["Animation"]["Time"], (bool)childEntity["Animation"]["Additive"]);
node->Parent = parentNode;
@@ -124,24 +128,26 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E
} else if (childEntity.HasComponent("Blend")) {
Node* node = new Node();
node->Entity = childEntity;
node->Name = childEntity.Name();
node->Parent = parentNode;
node->Type = NodeType::Blend;
(double&)childEntity["Blend"]["Weight"] = glm::clamp((float)(double)childEntity["Blend"]["Weight"], 0.f, 1.f);
(double&)childEntity["Blend"]["Weight"] = glm::clamp((double)childEntity["Blend"]["Weight"], 0.0, 1.0);
node->Weight = (double)childEntity["Blend"]["Weight"];
if (node->Weight < 1.f && node->Weight > 0.f) {
//if (node->Weight < 1.f && node->Weight > 0.f) {
node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity);
node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity);
} else if (node->Weight == 1.f) {
/* } else if (node->Weight == 1.f) {
node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity);
} else if (node->Weight == 0.f) {
node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity);
}
}*/
return node;
} else if (childEntity.HasComponent("BlendOverride")) {
Node* node = new Node();
node->Entity = childEntity;
node->Name = childEntity.Name();
node->Parent = parentNode;
node->Type = NodeType::Override;
@@ -150,6 +156,7 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E
return node;
} else if (childEntity.HasComponent("BlendAdditive")) {
Node* node = new Node();
node->Entity = childEntity;
node->Name = childEntity.Name();
node->Parent = parentNode;
node->Type = NodeType::Additive;
@@ -162,6 +169,75 @@ BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, E
return nullptr;
}
std::vector<BlendTree::Node*> BlendTree::FindNodesByName(std::string name)
{
std::vector<Node*> Nodes;
Node* currentNode = m_Root;
while (currentNode->Child[0] != nullptr) {
currentNode = currentNode->Child[0];
}
while (currentNode != nullptr) {
if(currentNode->Name == name) {
Nodes.push_back(currentNode);
}
currentNode = currentNode->Next();
}
return Nodes;
}
BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo)
{
std::vector<Node*> goalNodes = FindNodesByName(blendInfo.NodeName);
if(goalNodes.size() == 0) {
return blendInfo;
} else if(goalNodes.size() == 1) {
Node* currentNode = goalNodes[0]->Parent;
Node* lastNode = goalNodes[0];
while (currentNode != nullptr)
{
if(!currentNode->Entity.HasComponent("Blend")) {
return blendInfo;
}
double startWeight;
if(blendInfo.StartWeights.find(currentNode->Entity) != blendInfo.StartWeights.end()) {
startWeight = blendInfo.StartWeights.at(currentNode->Entity);
} else {
startWeight = currentNode->Weight;
blendInfo.StartWeights[currentNode->Entity] = startWeight;
}
double goalWeight;
if(currentNode->Child[0] == lastNode) {
goalWeight = 0.0;
} else if (currentNode->Child[1] == lastNode) {
goalWeight = 1.0;
}
double weight = ((goalWeight - startWeight) * blendInfo.progress) + startWeight;
(double&)currentNode->Entity["Blend"]["Weight"] = weight;
currentNode->Weight = weight;
lastNode = currentNode;
currentNode = currentNode->Parent;
}
} else if(goalNodes.size() >= 2) {
}
return blendInfo;
}
void BlendTree::Blend(std::map<int, glm::mat4>& pose)
{
Node* currentNode;
+1 -1
View File
@@ -142,7 +142,7 @@ void Renderer::Draw(RenderFrame& frame)
PerformanceTimer::StopTimer("Renderer-Depth");
}
PerformanceTimer::StartTimer("AO generation");
m_SSAOPass->Draw(m_PickingPass->DepthBuffer(), frame.RenderScenes.front()->Camera);
//m_SSAOPass->Draw(m_PickingPass->DepthBuffer(), frame.RenderScenes.front()->Camera);
GLuint ao = m_SSAOPass->SSAOTexture();
PerformanceTimer::StopTimer("AO generation");
for (auto scene : frame.RenderScenes){
+6 -10
View File
@@ -57,7 +57,7 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim
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::quat rotation = glm::normalize(glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress));
glm::vec3 scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
// Flag for no root motion
@@ -71,7 +71,7 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* anim
} else { // 1 keyframes for the current bone
currentFrame = boneKeyFrames.at(0);
boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale));
boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(glm::normalize(currentFrame.BoneProperties.Rotation)) * glm::scale(currentFrame.BoneProperties.Scale));
boneMatrices[bone->ID] = boneMatrix;// *bone->OffsetMatrix;
}
} else { // 0 keyframes for the current bone
@@ -244,7 +244,7 @@ glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animatio
}
if (progress > 1.0f || progress < 0.0f) {
LOG_INFO("Progress %f", progress);
//LOG_INFO("Progress %f", progress);
progress = glm::clamp(progress, 0.0f, 1.0f);
}
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
@@ -276,7 +276,7 @@ glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animatio
}
}
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> Skeleton::BlendPoses(const std::map<int, glm::mat4>& pose1, const std::map<int, glm::mat4>& pose2, double weight)
{
std::map<int, glm::mat4> finalPose;
@@ -285,8 +285,8 @@ std::map<int, glm::mat4> Skeleton::BlendPoses(const std::map<int, glm::mat4>& po
glm::mat4 blendedPose = glm::mat4(0);
if(pose1.find(boneID) != pose1.end() && pose2.find(boneID) != pose2.end()) {
blendedPose += pose1.at(boneID) * weight;
blendedPose += pose2.at(boneID) * (1.f - weight);
blendedPose += pose1.at(boneID) * (float)(1.0 - weight);
blendedPose += pose2.at(boneID) * (float)weight;
finalPose[boneID] = blendedPose;
} else if(pose1.find(boneID) != pose1.end()) {
finalPose[boneID] = pose1.at(boneID);
@@ -347,15 +347,11 @@ void Skeleton::GetFinalPose(std::map<int, glm::mat4>& boneMatrices, std::vector<
void Skeleton::AccumulateFinalPose(std::map<int, glm::mat4>& boneMatrices, std::map<int, glm::mat4>& boneTransforms, const Bone* bone, glm::mat4 parentMatrix)
{
glm::mat4 boneMatrix;
if (boneMatrices.find(bone->ID) != boneMatrices.end()) {
boneMatrix = parentMatrix * boneMatrices.at(bone->ID);
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
} else {
if (bone->Parent) {
boneMatrix = parentMatrix * (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix);