AutoAnimationBlend on unique node working but scale is not working correctly
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user