1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-22 02:12:45 +01:00

Refactor Animator to support multiple animations

This commit is contained in:
Daniel Evans 2014-05-31 12:15:20 +01:00
parent 04842a628a
commit 052ce629c4
5 changed files with 71 additions and 46 deletions

View File

@ -4,8 +4,7 @@
#include <glm/glm.hpp>
#include <glm/gtx/quaternion.hpp>
#include <vector>
#include <map>
#include <queue>
#include <cstdint>
class Animation;
@ -18,17 +17,25 @@ class ModelFrame;
*/
class Animator
{
Animation* animation;
/**
* @brief _animations Queue of animations to play.
*/
std::queue<Animation*> _animations;
/**
* @brief model The model being animated.
*/
Model* model;
// Used in determining how far the skeleton being animated has moved
// From it's local origin.
glm::vec3 lastRootPosition;
glm::quat lastRootRotation;
float time;
float serverTime;
float lastServerTime;
bool repeat;
void reset();
@ -45,8 +52,15 @@ public:
*/
void setAnimation(Animation* animation, bool repeat = true);
Animation* getAnimation() const
{ return animation; }
void queueAnimation(Animation* animation);
void next();
const std::queue<Animation*> getAnimationQueue() const
{ return _animations; }
const Animation* getAnimation() const
{ return _animations.empty() ? nullptr : _animations.front(); }
void setModel(Model* model);

View File

@ -77,9 +77,8 @@ bool Activities::GoTo::update(GTACharacter *character, GTAAIController *controll
bool Activities::EnterVehicle::update(GTACharacter *character, GTAAIController *controller)
{
if( entering ) {
std::cout << "Checking" << std::endl;
if( character->currentActivity == GTACharacter::Idle ) {
std::cout << "was idle" << std::endl;
// TODO: decouple from the character's animator.
if( character->animator->isCompleted() ) {
character->enterVehicle(vehicle, seat);
return true;
}
@ -87,9 +86,9 @@ bool Activities::EnterVehicle::update(GTACharacter *character, GTAAIController *
else {
glm::vec3 target = vehicle->getSeatEntryPosition(seat);
glm::vec3 targetDirection = target - character->getPosition();
targetDirection.z = 0.f;
if( glm::length(targetDirection) <= 0.4f ) {
std::cout << "enter started" << std::endl;
entering = true;
character->enterAction(GTACharacter::VehicleGetIn);
}

View File

@ -5,7 +5,7 @@
#include <glm/gtc/matrix_transform.hpp>
Animator::Animator()
: animation(nullptr), model(nullptr), time(0.f), serverTime(0.f), lastServerTime(0.f), repeat(true)
: model(nullptr), time(0.f), serverTime(0.f), lastServerTime(0.f), repeat(true)
{
}
@ -15,24 +15,32 @@ void Animator::reset()
time = 0.f;
serverTime = 0.f;
lastServerTime= 0.f;
if(model && animation) {
}
}
void Animator::setAnimation(Animation *animation, bool repeat)
{
if(animation == this->animation) {
if(!_animations.empty() && animation == _animations.front()) {
return;
}
this->animation = animation;
while(!_animations.empty()) _animations.pop();
queueAnimation(animation);
this->repeat = repeat;
reset();
}
void Animator::queueAnimation(Animation *animation)
{
_animations.push(animation);
}
void Animator::next()
{
_animations.pop();
reset();
}
void Animator::setModel(Model *model)
{
if(model == this->model) {
@ -46,23 +54,27 @@ void Animator::setModel(Model *model)
void Animator::tick(float dt)
{
if(! (animation && model)) {
if( model == nullptr || _animations.empty() ) {
return;
}
lastServerTime = serverTime;
serverTime += dt;
if( isCompleted() && ! repeat && _animations.size() > 1 ) {
next();
}
}
glm::vec3 Animator::getRootTranslation() const
{
// This is a pretty poor assumption.
if(model->frames[model->rootFrameIdx]->getChildren().size() > 0) {
if(!model->frames[model->rootFrameIdx]->getChildren().empty()
&& !_animations.empty()) {
ModelFrame* realRoot = model->frames[model->rootFrameIdx]->getChildren()[0];
auto it = animation->bones.find(realRoot->getName());
if(it != animation->bones.end()) {
float df = fmod(lastServerTime, this->animation->duration);
auto it = getAnimation()->bones.find(realRoot->getName());
if(it != getAnimation()->bones.end()) {
float df = fmod(lastServerTime, getAnimation()->duration);
float rt = getAnimationTime();
if(df < rt) {
auto lastKF = it->second->getInterpolatedKeyframe(df);
@ -82,38 +94,39 @@ glm::quat Animator::getRootRotation() const
glm::mat4 Animator::getFrameMatrix(ModelFrame* frame, float alpha) const
{
auto it = animation->bones.find(frame->getName());
if(it != animation->bones.end()) {
auto kf = it->second->getInterpolatedKeyframe(getAnimationTime(alpha));
glm::mat4 m;
if(it->second->type == AnimationBone::R00 || frame->getName() == "swaist") {
m = glm::translate(m, frame->getDefaultTranslation());
m = m * glm::mat4_cast(kf.rotation);
if(getAnimation()) {
auto it = getAnimation()->bones.find(frame->getName());
if(it != getAnimation()->bones.end()) {
auto kf = it->second->getInterpolatedKeyframe(getAnimationTime(alpha));
glm::mat4 m;
if(it->second->type == AnimationBone::R00 || frame->getName() == "swaist") {
m = glm::translate(m, frame->getDefaultTranslation());
m = m * glm::mat4_cast(kf.rotation);
}
else if(it->second->type == AnimationBone::RT0) {
m = glm::translate(m, kf.position);
m = m * glm::mat4_cast(kf.rotation);
}
else {
m = glm::translate(m, kf.position);
m = m * glm::mat4_cast(kf.rotation);
}
return m;
}
else if(it->second->type == AnimationBone::RT0) {
m = glm::translate(m, kf.position);
m = m * glm::mat4_cast(kf.rotation);
}
else {
m = glm::translate(m, kf.position);
m = m * glm::mat4_cast(kf.rotation);
}
return m;
}
else {
return frame->getTransform();
}
return frame->getTransform();
}
bool Animator::isCompleted() const
{
return serverTime >= animation->duration;
return getAnimation() ? serverTime >= getAnimation()->duration : true;
}
float Animator::getAnimationTime(float alpha) const
{
if(repeat) {
return fmod(serverTime + alpha, this->animation->duration);
return fmod(serverTime + alpha, getAnimation()->duration);
}
return serverTime + alpha;
}

View File

@ -139,7 +139,7 @@ void GTACharacter::tick(float dt)
if(animator->getAnimation() != animations.car_getin_lhs) {
animator->setAnimation(animations.car_getin_lhs, false);
}
else if( animator->isCompleted() ) {
else if( animator->getAnimation() == nullptr ) {
enterAction(Idle);
}
} break;

View File

@ -75,8 +75,7 @@ BOOST_AUTO_TEST_CASE(test_activities)
BOOST_CHECK_EQUAL( nullptr, character->getCurrentVehicle() );
for(float t = 0.f; t < 8.f; t+=(1.f/60.f)) {
controller->update(1.f/60.f);
for(float t = 0.f; t < 9.0f; t+=(1.f/60.f)) {
character->tick(1.f/60.f);
Global::get().e->dynamicsWorld->stepSimulation(1.f/60.f);
}