mirror of
https://github.com/barkeser2002/flower.git
synced 2026-09-25 17:56:17 +03:00
261 lines
5.7 KiB
C++
261 lines
5.7 KiB
C++
//
|
|
// Copyright(c) 2016-2017 benikabocha.
|
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
|
//
|
|
|
|
#include "MMDModel.h"
|
|
#include "MMDPhysics.h"
|
|
#include "VPDFile.h"
|
|
#include "VMDAnimation.h"
|
|
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
|
|
#include <Saba/Base/Log.h>
|
|
|
|
namespace saba
|
|
{
|
|
MMDPhysicsManager::MMDPhysicsManager()
|
|
{
|
|
}
|
|
|
|
MMDPhysicsManager::~MMDPhysicsManager()
|
|
{
|
|
for (auto& joint : m_joints)
|
|
{
|
|
m_mmdPhysics->RemoveJoint(joint.get());
|
|
}
|
|
m_joints.clear();
|
|
|
|
for (auto& rb : m_rigidBodys)
|
|
{
|
|
m_mmdPhysics->RemoveRigidBody(rb.get());
|
|
}
|
|
m_rigidBodys.clear();
|
|
|
|
m_mmdPhysics.reset();
|
|
}
|
|
|
|
bool MMDPhysicsManager::Create()
|
|
{
|
|
m_mmdPhysics = std::make_unique<MMDPhysics>();
|
|
return m_mmdPhysics->Create();
|
|
}
|
|
|
|
MMDPhysics* MMDPhysicsManager::GetMMDPhysics()
|
|
{
|
|
return m_mmdPhysics.get();
|
|
}
|
|
|
|
MMDRigidBody* MMDPhysicsManager::AddRigidBody()
|
|
{
|
|
SABA_ASSERT(m_mmdPhysics != nullptr);
|
|
auto rigidBody = std::make_unique<MMDRigidBody>();
|
|
auto ret = rigidBody.get();
|
|
m_rigidBodys.emplace_back(std::move(rigidBody));
|
|
|
|
return ret;
|
|
}
|
|
|
|
MMDJoint* MMDPhysicsManager::AddJoint()
|
|
{
|
|
SABA_ASSERT(m_mmdPhysics != nullptr);
|
|
auto joint = std::make_unique<MMDJoint>();
|
|
auto ret = joint.get();
|
|
m_joints.emplace_back(std::move(joint));
|
|
|
|
return ret;
|
|
}
|
|
|
|
void MMDModel::SaveBaseAnimation()
|
|
{
|
|
auto nodeMan = GetNodeManager();
|
|
for (size_t i = 0; i < nodeMan->GetNodeCount(); i++)
|
|
{
|
|
auto node = nodeMan->GetMMDNode(i);
|
|
node->SaveBaseAnimation();
|
|
}
|
|
|
|
auto morphMan = GetMorphManager();
|
|
for (size_t i = 0; i < morphMan->GetMorphCount(); i++)
|
|
{
|
|
auto morph = morphMan->GetMorph(i);
|
|
morph->SaveBaseAnimation();
|
|
}
|
|
|
|
auto ikMan = GetIKManager();
|
|
for (size_t i = 0; i < ikMan->GetIKSolverCount(); i++)
|
|
{
|
|
auto ikSolver = ikMan->GetMMDIKSolver(i);
|
|
ikSolver->SaveBaseAnimation();
|
|
}
|
|
}
|
|
|
|
void MMDModel::LoadBaseAnimation()
|
|
{
|
|
auto nodeMan = GetNodeManager();
|
|
for (size_t i = 0; i < nodeMan->GetNodeCount(); i++)
|
|
{
|
|
auto node = nodeMan->GetMMDNode(i);
|
|
node->LoadBaseAnimation();
|
|
}
|
|
|
|
auto morphMan = GetMorphManager();
|
|
for (size_t i = 0; i < morphMan->GetMorphCount(); i++)
|
|
{
|
|
auto morph = morphMan->GetMorph(i);
|
|
morph->LoadBaseAnimation();
|
|
}
|
|
|
|
auto ikMan = GetIKManager();
|
|
for (size_t i = 0; i < ikMan->GetIKSolverCount(); i++)
|
|
{
|
|
auto ikSolver = ikMan->GetMMDIKSolver(i);
|
|
ikSolver->LoadBaseAnimation();
|
|
}
|
|
}
|
|
|
|
void MMDModel::ClearBaseAnimation()
|
|
{
|
|
auto nodeMan = GetNodeManager();
|
|
for (size_t i = 0; i < nodeMan->GetNodeCount(); i++)
|
|
{
|
|
auto node = nodeMan->GetMMDNode(i);
|
|
node->ClearBaseAnimation();
|
|
}
|
|
|
|
auto morphMan = GetMorphManager();
|
|
for (size_t i = 0; i < morphMan->GetMorphCount(); i++)
|
|
{
|
|
auto morph = morphMan->GetMorph(i);
|
|
morph->ClearBaseAnimation();
|
|
}
|
|
|
|
auto ikMan = GetIKManager();
|
|
for (size_t i = 0; i < ikMan->GetIKSolverCount(); i++)
|
|
{
|
|
auto ikSolver = ikMan->GetMMDIKSolver(i);
|
|
ikSolver->ClearBaseAnimation();
|
|
}
|
|
}
|
|
|
|
namespace
|
|
{
|
|
glm::mat3 InvZ(const glm::mat3& m)
|
|
{
|
|
const glm::mat3 invZ = glm::scale(glm::mat4(1.0f), glm::vec3(1, 1, -1));
|
|
return invZ * m * invZ;
|
|
}
|
|
glm::quat InvZ(const glm::quat& q)
|
|
{
|
|
auto rot0 = glm::mat3_cast(q);
|
|
auto rot1 = InvZ(rot0);
|
|
return glm::quat_cast(rot1);
|
|
}
|
|
}
|
|
|
|
void MMDModel::UpdateAllAnimation(VMDAnimation * vmdAnim, float vmdFrame, float physicsElapsed)
|
|
{
|
|
if (vmdAnim != nullptr)
|
|
{
|
|
vmdAnim->Evaluate(vmdFrame);
|
|
}
|
|
|
|
UpdateMorphAnimation();
|
|
|
|
UpdateNodeAnimation(false);
|
|
|
|
UpdatePhysicsAnimation(physicsElapsed);
|
|
|
|
UpdateNodeAnimation(true);
|
|
}
|
|
|
|
void MMDModel::LoadPose(const VPDFile & vpd, int frameCount)
|
|
{
|
|
struct Pose
|
|
{
|
|
MMDNode* m_node;
|
|
glm::vec3 m_beginTranslate;
|
|
glm::vec3 m_endTranslate;
|
|
glm::quat m_beginRotate;
|
|
glm::quat m_endRotate;
|
|
};
|
|
std::vector<Pose> poses;
|
|
for (const auto& bone : vpd.m_bones)
|
|
{
|
|
auto nodeIdx = GetNodeManager()->FindNodeIndex(bone.m_boneName);
|
|
if (MMDNodeManager::NPos != nodeIdx)
|
|
{
|
|
Pose pose;
|
|
pose.m_node = GetNodeManager()->GetMMDNode(bone.m_boneName);
|
|
pose.m_beginTranslate = pose.m_node->GetAnimationTranslate();
|
|
pose.m_endTranslate = bone.m_translate * glm::vec3(1, 1, -1);
|
|
pose.m_beginRotate = pose.m_node->GetAnimationRotate();
|
|
pose.m_endRotate = InvZ(bone.m_quaternion);
|
|
poses.emplace_back(std::move(pose));
|
|
}
|
|
}
|
|
|
|
struct Morph
|
|
{
|
|
MMDMorph* m_morph;
|
|
float m_beginWeight;
|
|
float m_endWeight;
|
|
};
|
|
std::vector<Morph> morphs;
|
|
for (const auto& vpdMorph : vpd.m_morphs)
|
|
{
|
|
auto morphIdx = GetMorphManager()->FindMorphIndex(vpdMorph.m_morphName);
|
|
if (MMDMorphManager::NPos != morphIdx)
|
|
{
|
|
Morph morph;
|
|
morph.m_morph = GetMorphManager()->GetMorph(vpdMorph.m_morphName);
|
|
morph.m_beginWeight = morph.m_morph->GetWeight();
|
|
morph.m_endWeight = vpdMorph.m_weight;
|
|
morphs.emplace_back(std::move(morph));
|
|
}
|
|
}
|
|
|
|
// Physicsを反映する
|
|
for (int i = 0; i < frameCount; i++)
|
|
{
|
|
BeginAnimation();
|
|
|
|
// evaluate
|
|
float w = float(1 + i) / float(frameCount);
|
|
for (auto& pose : poses)
|
|
{
|
|
auto t = glm::mix(pose.m_beginTranslate, pose.m_endTranslate, w);
|
|
auto q = glm::slerp(pose.m_beginRotate, pose.m_endRotate, w);
|
|
pose.m_node->SetAnimationTranslate(t);
|
|
pose.m_node->SetAnimationRotate(q);
|
|
}
|
|
|
|
for (auto& morph : morphs)
|
|
{
|
|
auto weight = glm::mix(morph.m_beginWeight, morph.m_endWeight, w);
|
|
morph.m_morph->SetWeight(weight);
|
|
}
|
|
|
|
UpdateMorphAnimation();
|
|
UpdateNodeAnimation(false);
|
|
UpdatePhysicsAnimation(1.0f / 30.0f);
|
|
UpdateNodeAnimation(true);
|
|
|
|
EndAnimation();
|
|
}
|
|
|
|
//SaveBaseAnimation();
|
|
}
|
|
|
|
void MMDModel::UpdateAnimation()
|
|
{
|
|
UpdateMorphAnimation();
|
|
UpdateNodeAnimation(false);
|
|
}
|
|
|
|
void MMDModel::UpdatePhysics(float elapsed)
|
|
{
|
|
UpdatePhysicsAnimation(elapsed);
|
|
}
|
|
}
|