#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