// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdpch.h" ///////////// // INCLUDE // ///////////// // client #include "animation_misc.h" #include "animation.h" // 3d #include "nel/3d/u_track.h" /////////// // USING // /////////// using namespace NL3D; //////////// // METHOD // //////////// //--------------------------------------------------- // CAnimationMisc : // Constructor. //--------------------------------------------------- CAnimationMisc::CAnimationMisc() { }// CAnimationMisc // //--------------------------------------------------- // interpolate : // Function to get the position in animation at timeOffset. // \param idAnim : id of the animation. // \param timeOffset : time for the interpolation. // \param result : is the reference on the value to get the result (position). // \return bool : true if the parameter result is valid. //--------------------------------------------------- bool CAnimationMisc::interpolate(UAnimationSet *animationSet, uint idAnim, double timeOffset, NLMISC::CVector &result) { // Get the animation set. if(!animationSet) { nlwarning("CAnimationMisc::interpolate(CVector) : AnimationSet not allocated."); return false; } // Check the Animation if(idAnim == UAnimationSet::NotFound) return false; // Get the animation pointer. UAnimation *anim = animationSet->getAnimation(idAnim); if(!anim) { nlwarning("CAnimationMisc::interpolate(CVector) : animationSet.getAnimation(%d) return NULL.", idAnim); return false; } // Get the track for the position. UTrack* Track = anim->getTrackByName("pos"); if(!Track) { nlwarning("CAnimationMisc::interpolate(CVector) : track with the name 'pos' does not exist."); return false; } // Get the result. return Track->interpolate((CAnimationTime)timeOffset, result); }// interpolate // //--------------------------------------------------- // interpolate : // Function to get the rotation in an animation at timeOffset. // \param animationSet : search the animation in this set. // \param idAnim : id of the animation. // \param timeOffset : time for the interpolation. // \param result : is the reference on the value to get the result (rotation). // \return bool : true if the parameter result is valid. //--------------------------------------------------- bool CAnimationMisc::interpolate(UAnimationSet *animationSet, uint idAnim, double timeOffset, NLMISC::CQuat &result) { // Get the animation set. if(!animationSet) { nlwarning("CAnimationMisc::interpolate(CQuat) : AnimationSet not allocated."); return false; } // Check the Animation if(idAnim == UAnimationSet::NotFound) return false; // Get the animation pointer. UAnimation *anim = animationSet->getAnimation(idAnim); if(!anim) { nlwarning("CAnimationMisc::interpolate(CQuat) : animationSet.getAnimation(%d) return NULL.", idAnim); return false; } // Get the track for the position. UTrack* Track = anim->getTrackByName("rotquat"); if(!Track) { nlwarning("CAnimationMisc::interpolate(CQuat) : track with the name 'PathRotQuat' or 'rotquat' does not exist."); return false; } // Get the result. return Track->interpolate((CAnimationTime)timeOffset, result); }// interpolate // //--------------------------------------------------- // getAnimationLength : // Return an animation length (in sec). // \param animationSet : search the animation in this set. // \param string animName : Animation Name. // \return double : the length of the animation or 0 if any pb. // \warning This Method is slower than the one with the animation Id instead of the animation Name. //--------------------------------------------------- double CAnimationMisc::getAnimationLength(UAnimationSet *animationSet, const std::string &animName) { // Initialize the length to 0.0 like if there is an error. double length = 0.0; if(animationSet) { // Get the animation Id. uint idAnim = animationSet->getAnimationIdByName(animName); if(idAnim != UAnimationSet::NotFound) length = getAnimationLength(animationSet, idAnim); } // Return the lenght of the animation or 0 is any pb. return length; }// getAnimationLength // //--------------------------------------------------- // getAnimationLength : // Return an animation length (in sec). // \param animationSet : search the animation in this set. // \param idAnim : id of the animation. // \return double : the length of the animation or 0 if any pb. //--------------------------------------------------- double CAnimationMisc::getAnimationLength(UAnimationSet *animationSet, uint idAnim) { // Initialize the length to 0.0 like if there is an error. double length = 0.0; // Check _AnimationSet. if(animationSet) { // Check idAnim if(idAnim != UAnimationSet::NotFound) { // Get the animation pointer and get the length. UAnimation *anim = animationSet->getAnimation(idAnim); if(anim) length = anim->getEndTime() - anim->getBeginTime(); } } // Return the lenght of the animation or 0 is any pb. return length; }// getAnimationLength // //--------------------------------------------------- // getAnimationAverageSpeed : // Get the average speed of an animation (in meters/sec). // \param animationSet : search the animation in this set. // \param string animName : Animation Name. // \return double : the average speed (in m/s). //--------------------------------------------------- double CAnimationMisc::getAnimationAverageSpeed(UAnimationSet *animationSet, const std::string &animName) { if(animationSet) { // Get the animation Id. uint idAnim = animationSet->getAnimationIdByName(animName); if(idAnim != UAnimationSet::NotFound) return getAnimationAverageSpeed(animationSet, idAnim); } else nlwarning("CAnimationMisc::getAnimationAverageSpeed : animationSet is NULL"); // Return the animation average speed. return 0.0; }// getAnimationAverageSpeed // //--------------------------------------------------- // getAnimationAverageSpeed : // Get the average speed of an animation (in meters/sec). // \param animationSet : search the animation in this set. // \param idAnim : id of the animation. // \return double : the average speed (in m/s). //--------------------------------------------------- double CAnimationMisc::getAnimationAverageSpeed(UAnimationSet *animationSet, uint idAnim) { // Initialize the length to 0.0 like if there is an error. double length = getAnimationLength(animationSet, idAnim); // Check the length. if(length <= 0.0) { nlwarning("CEntityAnimationManager::getAnimationAverageSpeed : length <= 0.0 -> return speed = 0.0"); return 0.0; } // Get the distance done by the animation. double move = 0.0; NLMISC::CVector startPos, endPos; if(interpolate(animationSet, idAnim, 0.0, startPos)) { if(interpolate(animationSet, idAnim, length, endPos)) { NLMISC::CVector mov = endPos - startPos; move = mov.norm(); } } // Return the animation average speed. return (move / length); }// getAnimationAverageSpeed // //--------------------------------------------------- // getAnimationRotation : // Get the rotation done by the animation (in radian). // \param animationSet : search the animation in this set. // \param string animName : Animation Name. // \return double : the rotation (in radian). //--------------------------------------------------- double CAnimationMisc::getAnimationRotation(NL3D::UAnimationSet *animationSet, const std::string &animName) { if(animationSet) { // Get the animation Id. uint idAnim = animationSet->getAnimationIdByName(animName); if(idAnim != UAnimationSet::NotFound) return getAnimationRotation(animationSet, idAnim); } else nlwarning("CAnimationMisc::getAnimationRotation : animationSet is NULL"); // Return the animation average speed. return 0.0; }// getAnimationRotation // //--------------------------------------------------- // getAnimationRotation : // Get the rotation done by the animation (in radian). // \param animationSet : search the animation in this set. // \param idAnim : id of the animation. // \return double : the rotation (in radian). //--------------------------------------------------- double CAnimationMisc::getAnimationRotation(NL3D::UAnimationSet *animationSet, uint idAnim) { // Check the animation Id. if(idAnim != CAnimation::UnknownAnim) { CQuat currentAnimRotStart, currentAnimRotEnd; if(CAnimationMisc::interpolate(animationSet, idAnim, 0.0, currentAnimRotStart)) { double animLength = CAnimationMisc::getAnimationLength(animationSet, idAnim); if(CAnimationMisc::interpolate(animationSet, idAnim, animLength, currentAnimRotEnd)) { currentAnimRotStart.invert(); CQuat currentAnimRot = currentAnimRotStart * currentAnimRotEnd; return fabs(currentAnimRot.getAngle()); } } } return 0.f; }// getAnimationRotation // //----------------------------------------------- // Get the vector covered by the given animation. // \param animationSet : search the animation in this set. // \param idAnim : id of the animation. // \param move : filled with the vector of the move if possible // \return bool : true if 'move' has been filled, else false. //----------------------------------------------- bool CAnimationMisc::getAnimationMove(NL3D::UAnimationSet *animationSet, uint idAnim, NLMISC::CVector &move) // static { CVector startPos, endPos; if(CAnimationMisc::interpolate(animationSet, idAnim, 0.0, startPos)) { double animLength = CAnimationMisc::getAnimationLength(animationSet, idAnim); if(animLength) { if(CAnimationMisc::interpolate(animationSet, idAnim, animLength, endPos)) { // Well Done. move = endPos - startPos; return true; } } } // Something Wrong -> return false. return false; }// getAnimationMove //