// 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 length 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 length 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 //