NL3D::CTargetAnimCtrl Class Reference

#include <target_anim_ctrl.h>

Inheritance diagram for NL3D::CTargetAnimCtrl:

NL3D::IAnimCtrl

Detailed Description

AnimCtrl used to constraint a bone to follow a target, either given by Position or Direction. Typical use for Head control Use TargetMode is better than computing Direction from Previous rendered Bone WorldMatrix (one frame late). The ctrl support AngleBlocking, and MaxBoneAngularSpeed (avoid strange head pop). The Bone must be in RotQuat mode, else the ctrl does nothing.
Author:
Lionel Berenguier

Nevrax France

Date:
2003

Definition at line 48 of file target_anim_ctrl.h.

Public Types

enum  TMode { TargetMode = 0, DirectionMode, NumMode }

Public Member Functions

 CTargetAnimCtrl ()
 Constructor.

virtual void execute (CSkeletonModel *model, CBone *bone)
 Called at compute() time.

virtual ~CTargetAnimCtrl ()

Data Fields

TMode Mode
 Target controled or direction controled. Default to DirectionMode.

Target and Direction specific
CQuat CurrentWorldDirection
 For DirectionMode, the WorldRotation to apply to the bone. NB: modified in execute() if TargetMode.

CVector EyePos
 For TargetMode only, the Pos of eyes relative to the bone controlled. Default to (0,0,0).

CVector WorldTarget
 For TargetMode, the world Position of the target.

Common
CQuat DefaultWorldDirection
 This give The World Orientation when the Mesh is in bind Pos (default to "LookBack").

bool Enabled
float MaxAngle
 The Maximum angle of rotation that can be performed between the Default Direction and Current Direction. Default to Pi/3.

float MaxAngularVelocity
 The Maximum Angular Velocity the ctrl can perform. Default to 2*Pi per second.


Private Member Functions

CQuat getCurrentLSRotationFromBone (CSkeletonModel *model, CBone *bone)

Private Attributes

bool _EnableToDisableTransition
bool _LastEnabled
 This tells that a Enable/Disable transition is in progress.

CQuat _LastLSRotation
 The last rotation computed (in LocalSkeleton Space). Used to smooth transition.


Member Enumeration Documentation

enum NL3D::CTargetAnimCtrl::TMode
 

Enumeration values:
TargetMode 
DirectionMode 
NumMode 

Definition at line 52 of file target_anim_ctrl.h.


Constructor & Destructor Documentation

NL3D::CTargetAnimCtrl::CTargetAnimCtrl  ) 
 

Constructor.

Definition at line 40 of file target_anim_ctrl.cpp.

References _EnableToDisableTransition, _LastEnabled, DefaultWorldDirection, DirectionMode, Enabled, EyePos, MaxAngle, MaxAngularVelocity, Mode, NLMISC::Pi, NLMISC::CQuatT< float >::set(), and WorldTarget.

00041 {
00042         Mode= DirectionMode;
00043         WorldTarget= CVector::Null;
00044         EyePos= CVector::Null;
00045         // Default Direction to "LookBack".
00046         DefaultWorldDirection.set(0,0,1,0);
00047         MaxAngle= (float)Pi/3;
00048         MaxAngularVelocity= (float)(2*Pi);
00049         Enabled= true;
00050         _EnableToDisableTransition= false;
00051         _LastEnabled= true;
00052 }

NL3D::CTargetAnimCtrl::~CTargetAnimCtrl  )  [virtual]
 

Definition at line 56 of file target_anim_ctrl.cpp.

00057 {
00058 }


Member Function Documentation

void NL3D::CTargetAnimCtrl::execute CSkeletonModel model,
CBone bone
[virtual]
 

Called at compute() time.

Implements NL3D::IAnimCtrl.

Definition at line 62 of file target_anim_ctrl.cpp.

References _EnableToDisableTransition, _LastEnabled, _LastLSRotation, NLMISC::CAngleAxis::Angle, NL3D::CSkeletonModel::Bones, NLMISC::clamp(), NL3D::CBone::compute(), NLMISC::CQuatT< float >::conjugate(), CurrentWorldDirection, DefaultWorldDirection, Enabled, EyePos, NLMISC::CQuatT< float >::getAngle(), NLMISC::CQuatT< float >::getAngleAxis(), NL3D::CBone::getBoneBase(), getCurrentLSRotationFromBone(), NL3D::CScene::getEllapsedTime(), NL3D::CBone::getFatherId(), NL3D::CBone::getLocalSkeletonMatrix(), NL3D::CTransform::getOwnerScene(), NLMISC::CMatrix::getRot(), NL3D::ITransformable::getTransformMode(), NL3D::CTransform::getWorldMatrix(), NL3D::CBone::getWorldMatrix(), NL3D::CBoneBase::InvBindPos, NLMISC::CQuatT< float >::makeClosest(), MaxAngle, MaxAngularVelocity, Mode, NLMISC::CMatrix::normalize(), NLMISC::CVector::normed(), NLMISC::CQuatT< float >::setAngleAxis(), NLMISC::CMatrix::setRot(), NL3D::ITransformable::setRotQuat(), and WorldTarget.

00063 {
00064         // no op if req not met
00065         if(!bone || !model || bone->getTransformMode()!=ITransformable::RotQuat)
00066                 return;
00067 
00068         // If the user changed the Enabled state, must do a transition.
00069         if(_LastEnabled!=Enabled)
00070         {
00071                 _LastEnabled= Enabled;
00072                 // if re-enable the control while completely disabled before
00073                 if(Enabled && !_EnableToDisableTransition)
00074                 {
00075                         // set the LastLSRotation so that it match the current anim ones.
00076                         _LastLSRotation= getCurrentLSRotationFromBone(model, bone);
00077                 }
00078                 // if disable the ctrl, then do a transition first
00079                 if(!Enabled)
00080                 {
00081                         _EnableToDisableTransition= true;
00082                 }
00083         }
00084 
00085         // If not enabled, and not in transition, no op.
00086         if( !Enabled && !_EnableToDisableTransition)
00087                 return;
00088 
00089         // If Target mode, compute CurrentWorldDirection
00090         // ***********
00091         // NB: does need to compute direction if disabled (even if in transition)
00092         if(Mode==TargetMode && Enabled)
00093         {
00094                 // get the eye pos in world.
00095                 CVector worldEye= bone->getWorldMatrix()*EyePos;
00096                 // get the world dir
00097                 CVector worldDir= (WorldTarget - worldEye).normed();
00098                 // get the associated quat
00099                 CMatrix mat;
00100                 mat.setRot(CVector::I, worldDir, CVector::K);
00101                 mat.normalize(CMatrix::YZX);
00102                 CurrentWorldDirection= mat.getRot();
00103         }
00104 
00105 
00106         // compute rotation to apply In LocalSkeleton Space
00107         // ***********
00108         CQuat           currentLSRotation;
00109 
00110         /* Get the Skeleton default WorldMatrix (bind pos). used later
00111                 TRICK: to get the default Skeleton WorldMatrix, get it from Bone[0] (ie "Bip01")
00112                 We cannot use the Default Pos/Rot of the skeleton model because of export bug (not exported...)
00113                 So, since Bip01 as no Local Rot (yes, its true, exporter report all Bip01 rots on Skeleton), 
00114                 we are sure that Bip01 BindPos is the default Skeleton World Matrix.
00115         */
00116         CQuat           rootInvBP= model->Bones[0].getBoneBase().InvBindPos.getRot();
00117 
00118         // If ctrl not enabled, take the LSRotation from the animation
00119         if(!Enabled)
00120         {
00121                 currentLSRotation= getCurrentLSRotationFromBone(model, bone);
00122         }
00123         else
00124         {
00125                 // Get the wanted direction in LocalSkeleton Space. 
00126                 CQuat           currentLSDirection;
00127 
00128                 // Get the current wanted WorldDirection into LocalSkeleton space (hence using current skeleton WorldMatrix).
00129                 CMatrix         toLSSpace= model->getWorldMatrix();
00130                 currentLSDirection= toLSSpace.getRot().conjugate() * CurrentWorldDirection;
00131 
00132                 // Get the default WorldDirection into LocalSkeleton space (hence using default skeleton WorldMatrix).
00133                 CQuat           defaultLSDirection= rootInvBP * DefaultWorldDirection;
00134 
00135                 /* get the rotation to apply to the bone when it is in bind Pos. If this quat is identity, 
00136                         then the bone will be in default (or bind) pos.
00137                         It is in essence the "rotation to apply to defaultDirection in LS space, in order to get 
00138                         the wanted current direction in LS space".
00139                         The makeClosest() is here just to ensure that the resulting angle<Pi (for clamp direction later)
00140                 */
00141                 currentLSDirection.makeClosest(defaultLSDirection);
00142                 currentLSRotation= currentLSDirection * defaultLSDirection.conjugate();
00143         }
00144 
00145 
00146         // Clamp direction, and smooth direction changes.
00147         // ***********
00148         // if not enabled, then LSRotation comes from the animation => do not clamp
00149         if(Enabled)
00150         {
00151                 // to AngleAxis.
00152                 CAngleAxis      angleAxis= currentLSRotation.getAngleAxis();
00153                 // Clamp the angle
00154                 clamp(angleAxis.Angle, -MaxAngle, MaxAngle);
00155                 // back To Quat.
00156                 currentLSRotation.setAngleAxis(angleAxis);
00157         }
00158 
00159         // get the dt of the scene.
00160         CScene  *scene= model->getOwnerScene();
00161         float   sceneDt= scene->getEllapsedTime();
00162         float   maxDeltaAngle= MaxAngularVelocity*sceneDt;
00163         // get the quat that change from LastRotation to CurrentRotation
00164         CQuat   rotMod= _LastLSRotation.conjugate() * currentLSRotation;
00165         // compute how many rotation we are allowed to do.
00166         float   rotModAngle= (float)fabs(rotMod.getAngle());
00167         bool    rotSpeedClamped= false;
00168         if(rotModAngle)
00169         {
00170                 float   factor= (float)fabs(maxDeltaAngle) / rotModAngle;
00171                 // If cannot do all the rotation this frame
00172                 if(factor<1)
00173                 {
00174                         // then slerp between last and current rotation
00175                         currentLSRotation.makeClosest(_LastLSRotation);
00176                         currentLSRotation= CQuat::slerp(_LastLSRotation, currentLSRotation, factor);
00177                         rotSpeedClamped= true;
00178                 }
00179         }
00180 
00181         // if the rotation has not been clamped for speed consideration, and if !Enabed, it's mean we have ended 
00182         // the transition => no more compute next time
00183         if(!Enabled && !rotSpeedClamped)
00184                 _EnableToDisableTransition= false;
00185 
00186         // bkup last rotation
00187         _LastLSRotation= currentLSRotation;
00188 
00189         // Apply the weighted Rotation to the bone
00190         // ***********
00191         // Get the bone Bind Pos in LocalSkeleton space (hence using Default Skeleton WorldMatrix)
00192         CQuat   boneBindPosInWorld= bone->getBoneBase().InvBindPos.getRot().conjugate();
00193         CQuat   boneBindPosInLS= rootInvBP * boneBindPosInWorld;
00194         // rotate it to match our wanted direction.
00195         boneBindPosInLS= currentLSRotation * boneBindPosInLS;
00196 
00197         // get it in bone local space.
00198         // get the Bone Parent LocalSkeletonMatrix
00199         CBone   *boneParent= bone->getFatherId()==-1? NULL : &model->Bones[bone->getFatherId()];
00200         CQuat   currentLocalQuat;
00201         if(!boneParent)
00202                 currentLocalQuat= boneBindPosInLS;
00203         else
00204         {
00205                 // compute the rotation to apply, in local space
00206                 CQuat           qp= boneParent->getLocalSkeletonMatrix().getRot();
00207                 currentLocalQuat= qp.conjugate() * boneBindPosInLS;
00208         }
00209 
00210         // set the new LocalRotQuat
00211         bone->setRotQuat(currentLocalQuat);
00212         // and recompute the bone (but without AnimCtrl of course :) )
00213         bone->compute(boneParent, model->getWorldMatrix(), NULL);
00214 
00215 }

CQuat NL3D::CTargetAnimCtrl::getCurrentLSRotationFromBone CSkeletonModel model,
CBone bone
[private]
 

Definition at line 219 of file target_anim_ctrl.cpp.

References NL3D::CSkeletonModel::Bones, NLMISC::CQuatT< float >::conjugate(), NL3D::CBone::getBoneBase(), NL3D::CBone::getLocalSkeletonMatrix(), NLMISC::CMatrix::getRot(), NL3D::CBoneBase::InvBindPos, and NLMISC::CQuatT< float >::makeClosest().

Referenced by execute().

00220 {
00221         // get the current rotation matrix (qmat) of this bone, in LS space
00222         CQuat   currentLSRot= bone->getLocalSkeletonMatrix().getRot();
00223 
00224         // get the default bindPos (qb) rotation of this bone, in LS space.
00225         CQuat   boneBindPosInWorld= bone->getBoneBase().InvBindPos.getRot().conjugate();
00226         CQuat   rootInvBP= model->Bones[0].getBoneBase().InvBindPos.getRot();
00227         CQuat   boneBindPosInLS= rootInvBP * boneBindPosInWorld;
00228 
00229         // The rotation (qrot) is computed such that qmat= qrot * qb
00230         currentLSRot.makeClosest(boneBindPosInLS);
00231         return currentLSRot * boneBindPosInLS.conjugate();
00232 }


Field Documentation

bool NL3D::CTargetAnimCtrl::_EnableToDisableTransition [private]
 

Definition at line 99 of file target_anim_ctrl.h.

Referenced by CTargetAnimCtrl(), and execute().

bool NL3D::CTargetAnimCtrl::_LastEnabled [private]
 

This tells that a Enable/Disable transition is in progress.

Definition at line 98 of file target_anim_ctrl.h.

Referenced by CTargetAnimCtrl(), and execute().

CQuat NL3D::CTargetAnimCtrl::_LastLSRotation [private]
 

The last rotation computed (in LocalSkeleton Space). Used to smooth transition.

Definition at line 95 of file target_anim_ctrl.h.

Referenced by execute().

CQuat NL3D::CTargetAnimCtrl::CurrentWorldDirection
 

For DirectionMode, the WorldRotation to apply to the bone. NB: modified in execute() if TargetMode.

Definition at line 65 of file target_anim_ctrl.h.

Referenced by execute().

CQuat NL3D::CTargetAnimCtrl::DefaultWorldDirection
 

This give The World Orientation when the Mesh is in bind Pos (default to "LookBack").

Definition at line 75 of file target_anim_ctrl.h.

Referenced by CTargetAnimCtrl(), and execute().

bool NL3D::CTargetAnimCtrl::Enabled
 

This enable or disable the ctrl. When disabled or enabled, the ctrl ensure that the movement does not "pop", respecting MaxAngularVelocity. Default to true.

Definition at line 73 of file target_anim_ctrl.h.

Referenced by CTargetAnimCtrl(), and execute().

CVector NL3D::CTargetAnimCtrl::EyePos
 

For TargetMode only, the Pos of eyes relative to the bone controlled. Default to (0,0,0).

Definition at line 63 of file target_anim_ctrl.h.

Referenced by CTargetAnimCtrl(), and execute().

float NL3D::CTargetAnimCtrl::MaxAngle
 

The Maximum angle of rotation that can be performed between the Default Direction and Current Direction. Default to Pi/3.

Definition at line 77 of file target_anim_ctrl.h.

Referenced by CTargetAnimCtrl(), and execute().

float NL3D::CTargetAnimCtrl::MaxAngularVelocity
 

The Maximum Angular Velocity the ctrl can perform. Default to 2*Pi per second.

Definition at line 79 of file target_anim_ctrl.h.

Referenced by CTargetAnimCtrl(), and execute().

TMode NL3D::CTargetAnimCtrl::Mode
 

Target controled or direction controled. Default to DirectionMode.

Definition at line 56 of file target_anim_ctrl.h.

Referenced by CTargetAnimCtrl(), and execute().

CVector NL3D::CTargetAnimCtrl::WorldTarget
 

For TargetMode, the world Position of the target.

Definition at line 61 of file target_anim_ctrl.h.

Referenced by CTargetAnimCtrl(), and execute().


The documentation for this class was generated from the following files:
Generated on Tue Mar 16 07:47:42 2004 for NeL by doxygen 1.3.6