1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-25 03:42:48 +01:00

Change Animator to animate Frames directly instead of Skeleton

This commit is contained in:
Daniel Evans 2017-01-08 03:28:33 +00:00
parent 3163a5dd57
commit ec5f1d7b55
5 changed files with 31 additions and 57 deletions

View File

@ -3,9 +3,9 @@
#include <engine/Animator.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <loaders/LoaderDFF.hpp>
#include <queue>
Animator::Animator(Clump* model, Skeleton* skeleton)
: model(model), skeleton(skeleton) {
Animator::Animator(Clump* model) : model(model) {
}
void Animator::tick(float dt) {
@ -18,21 +18,21 @@ void Animator::tick(float dt) {
glm::quat rotation;
};
#if 0
// Blend all active animations together
std::map<unsigned int, BoneTransform> blendFrames;
std::map<ModelFrame*, BoneTransform> blendFrames;
#endif
for (AnimationState& state : animations) {
RW_CHECK(state.animation != nullptr,
"AnimationState with no animation");
if (state.animation == nullptr) continue;
if (state.boneInstances.size() == 0) {
for (unsigned int f = 0; f < model->frames.size(); ++f) {
auto bit =
state.animation->bones.find(model->frames[f]->getName());
if (bit != state.animation->bones.end()) {
state.boneInstances.insert({bit->second, {f}});
if (state.boneInstances.empty()) {
for (const auto& bone : state.animation->bones) {
auto frame = model->findFrame(bone.first);
if (!frame) {
continue;
}
state.boneInstances.insert({bone.second, frame});
}
}
@ -72,23 +72,20 @@ void Animator::tick(float dt) {
blendFrames[b.second.frameIndex] = xform;
}
#else
blendFrames[b.second.frameIndex] = xform;
b.second->setTranslation(b.second->getDefaultTranslation() +
xform.translation);
b.second->setRotation(glm::mat3_cast(xform.rotation));
#endif
}
}
#if 0
for (auto& p : blendFrames) {
auto& data = skeleton->getData(p.first);
Skeleton::FrameData fd;
fd.b = data.a;
fd.enabled = data.enabled;
fd.a.translation = model->frames[p.first]->getDefaultTranslation() +
p.second.translation;
fd.a.rotation = p.second.rotation;
skeleton->setData(p.first, fd);
p.first->setTranslation(p.first->getDefaultTranslation() +
p.second.translation);
p.first->setRotation(glm::mat3_cast(p.second.rotation));
}
#endif
}
bool Animator::isCompleted(unsigned int slot) const {

View File

@ -11,8 +11,6 @@
class Clump;
class ModelFrame;
class Skeleton;
/**
* @brief calculates animation frame matrices, as well as procedural frame
* animation.
@ -24,13 +22,6 @@ class Skeleton;
* The Animator will blend all active animations together.
*/
class Animator {
/**
* @brief Stores data required to animate a model frame
*/
struct BoneInstanceData {
unsigned int frameIndex;
};
/**
* @brief The AnimationState struct stores information about playing
* animations
@ -43,7 +34,7 @@ class Animator {
float speed;
/// Automatically restart
bool repeat;
std::map<AnimationBone*, BoneInstanceData> boneInstances;
std::map<AnimationBone*, ModelFrame*> boneInstances;
};
/**
@ -51,18 +42,13 @@ class Animator {
*/
Clump* model;
/**
* @brief Skeleton instance.
*/
Skeleton* skeleton;
/**
* @brief Currently playing animations
*/
std::vector<AnimationState> animations;
public:
Animator(Clump* model, Skeleton* skeleton);
Animator(Clump* model);
Animation* getAnimation(unsigned int slot) {
if (slot < animations.size()) {

View File

@ -74,8 +74,7 @@ CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos,
setClump(ClumpPtr(info->getModel()->clone()));
if (info->getModel()) {
setModel(info->getModel());
skeleton = new Skeleton;
animator = new Animator(getModel(), skeleton);
animator = new Animator(getClump().get());
createActor();
}
@ -251,10 +250,6 @@ glm::vec3 CharacterObject::updateMovementAnimation(float dt) {
rootBone->getInterpolatedKeyframe(animTime + step).position;
glm::vec3 d = (b - a);
animTranslate.y += d.y;
Skeleton::FrameData fd = skeleton->getData(root->getIndex());
fd.a.translation.y = 0.f;
skeleton->setData(root->getIndex(), fd);
}
}
@ -278,6 +273,7 @@ void CharacterObject::tick(float dt) {
void CharacterObject::setRotation(const glm::quat& orientation) {
m_look.x = glm::roll(orientation);
rotation = orientation;
getClump()->getFrame()->setRotation(glm::mat3_cast(rotation));
}
#include <algorithm>
@ -291,15 +287,13 @@ void CharacterObject::changeCharacterModel(const std::string& name) {
engine->data->loadTXD(modelName + ".txd");
auto newmodel = engine->data->loadClump(modelName + ".dff");
if (skeleton) {
if (animator) {
delete animator;
delete skeleton;
}
setModel(newmodel);
skeleton = new Skeleton;
animator = new Animator(getModel(), skeleton);
animator = new Animator(getClump().get());
}
void CharacterObject::updateCharacter(float dt) {

View File

@ -14,8 +14,7 @@ CutsceneObject::CutsceneObject(GameWorld *engine, const glm::vec3 &pos,
else {
setModel(getModelInfo<ClumpModelInfo>()->getModel());
}
skeleton = new Skeleton;
animator = new Animator(getModel(), skeleton);
animator = new Animator(getModel());
}
CutsceneObject::~CutsceneObject() {

View File

@ -17,7 +17,7 @@ BOOST_AUTO_TEST_CASE(test_matrix) {
* frame #s. */
auto test_model = Global::get().d->loadClump("player.dff");
Animator animator(test_model, &skeleton);
Animator animator(test_model);
animation.duration = 1.f;
animation.bones["player"] = new AnimationBone{
@ -35,17 +35,15 @@ BOOST_AUTO_TEST_CASE(test_matrix) {
animator.tick(0.0f);
BOOST_CHECK(skeleton.getData(0).a.translation ==
glm::vec3(0.f, 0.f, 0.f));
BOOST_CHECK(skeleton.getData(0).b.translation ==
const auto& root = test_model->findFrame("player");
BOOST_CHECK(glm::vec3(root->getTransform()[3]) ==
glm::vec3(0.f, 0.f, 0.f));
animator.tick(1.0f);
BOOST_CHECK(skeleton.getData(0).a.translation ==
BOOST_CHECK(glm::vec3(root->getTransform()[3]) ==
glm::vec3(0.f, 1.f, 0.f));
BOOST_CHECK(skeleton.getData(0).b.translation ==
glm::vec3(0.f, 0.f, 0.f));
}
}
#endif