From 12b0b74d43b7d93eee82ae6fa3dced499cd8a1f6 Mon Sep 17 00:00:00 2001 From: KT Date: Tue, 19 Oct 2021 14:03:28 -0500 Subject: Publish a4 --- dev/a4-dance/animated_character.cc | 245 +++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 dev/a4-dance/animated_character.cc (limited to 'dev/a4-dance/animated_character.cc') diff --git a/dev/a4-dance/animated_character.cc b/dev/a4-dance/animated_character.cc new file mode 100644 index 0000000..110dbbe --- /dev/null +++ b/dev/a4-dance/animated_character.cc @@ -0,0 +1,245 @@ +#include "animated_character.h" +#include "amc_util.h" + +#include +#include +#include +#include + + +AnimatedCharacter::AnimatedCharacter(const std::string &asf_filename) : + fps_(120), elapsed_since_last_frame_(0.0f), current_frame_(0) +{ + LoadSkeleton(asf_filename); +} + +AnimatedCharacter::AnimatedCharacter() : + fps_(120), elapsed_since_last_frame_(0.0f), current_frame_(0) +{ +} + +AnimatedCharacter::~AnimatedCharacter() { +} + + +void AnimatedCharacter::LoadSkeleton(const std::string &asf_filename) { + skeleton_.LoadFromASF(asf_filename); +} + + +void AnimatedCharacter::Play(const MotionClip &motion_clip) { + motion_queue_.clear(); + motion_queue_.push_back(motion_clip); + current_frame_ = 0; +} + + +void AnimatedCharacter::Queue(const MotionClip &motion_clip) { + if (motion_queue_.size() == 0) { + Play(motion_clip); + } + else { + motion_queue_.push_back(motion_clip); + } +} + + +void AnimatedCharacter::ClearQueue() { + motion_queue_.clear(); +} + + +void AnimatedCharacter::OverlayClip(const MotionClip &clip, int num_transition_frames) { + overlay_clip_ = clip; + overlay_transition_frames_ = num_transition_frames; + overlay_frame_ = 0; +} + + +void AnimatedCharacter::AdvanceAnimation(double dt) { + if (motion_queue_.size() == 0) { + pose_ = Pose(); + } + else { + elapsed_since_last_frame_ += dt; + + double frames_to_advance = fps_ * elapsed_since_last_frame_; + double whole_frames; + double frac = modf(frames_to_advance, &whole_frames); + int nframes = (int)whole_frames; + elapsed_since_last_frame_ = frac / fps_; + + for (int i=0; i= motion_queue_[0].size()) { + // loop back to the first frame + current_frame_ = 0; + // if there are more motions in the queue then pop this one and goto the next + if (motion_queue_.size() > 1) { + motion_queue_.erase(motion_queue_.begin()); + } + } + + // advance the overlay clip if there is one + if (overlay_clip_.size()) { + overlay_frame_++; + // handle end case + if (overlay_frame_ >= overlay_clip_.size()) { + // done playing overlay, reset frame counter and clear the overlay clip + overlay_frame_ = 0; + overlay_clip_ = MotionClip(); + } + } + + // update the pose based on new frames + CalcCurrentPose(); + + // add to the translation matrix for the case when relative root motion is used + accum_translation_matrix_ = accum_translation_matrix_ * pose_.root_relative_translation(); + } + } +} + + +void AnimatedCharacter::CalcCurrentPose() { + if (!overlay_clip_.size()) { + // no overaly track, motion is entirely from the base track (i.e., the motion queue) + pose_ = motion_queue_[0][current_frame_]; + } + else { + // there is an active overlay track + if (overlay_frame_ < overlay_transition_frames_) { + // fade in the overlay + float alpha = (float)overlay_frame_/(float)overlay_transition_frames_; + pose_ = motion_queue_[0][current_frame_].Lerp(overlay_clip_[overlay_frame_], alpha); + } + else if (overlay_frame_ > overlay_clip_.size() - overlay_transition_frames_) { + // fade out the overlay + float alpha = (float)(overlay_clip_.size() - overlay_frame_)/(float)overlay_transition_frames_; + pose_ = motion_queue_[0][current_frame_].Lerp(overlay_clip_[overlay_frame_], alpha); + } + else { + // overlay is completely faded in, we don't see the base track at all + pose_ = overlay_clip_[overlay_frame_]; + } + } +} + + +Skeleton* AnimatedCharacter::skeleton_ptr() { + return &skeleton_; +} + + +void AnimatedCharacter::set_fps(int fps) { + fps_ = fps; +} + + +int AnimatedCharacter::fps() { + return fps_; +} + + + +void AnimatedCharacter::Draw(const Matrix4 &model_matrix, const Matrix4 &view_matrix, const Matrix4 &proj_matrix, + bool use_absolute_position) +{ + Matrix4 character_root_transform; + if (use_absolute_position) { + // set root position based on the absolute position in the mocap data + character_root_transform = model_matrix * pose_.RootTransform(); + } + else { + // set root position based on the relative updates accumulated each frame + character_root_transform = model_matrix * accum_translation_matrix_ * pose_.root_rotation(); + } + + for (int i=0; i