00001 
00032 
00033 
00034 
00035 #include "linden_common.h"
00036 
00037 #include "lltargetingmotion.h"
00038 #include "llcharacter.h"
00039 #include "v3dmath.h"
00040 #include "llcriticaldamp.h"
00041 
00042 
00043 
00044 
00045 const F32 TORSO_TARGET_HALF_LIFE = 0.25f;
00046 const F32 MAX_TIME_DELTA = 2.f; 
00047 const F32 TARGET_PLANE_THRESHOLD_DOT = 0.6f;
00048 const F32 TORSO_ROT_FRACTION = 0.5f;
00049 
00050 
00051 
00052 
00053 
00054 LLTargetingMotion::LLTargetingMotion(const LLUUID &id) : LLMotion(id)
00055 {
00056         mCharacter = NULL;
00057         mName = "targeting";
00058 }
00059 
00060 
00061 
00062 
00063 
00064 
00065 LLTargetingMotion::~LLTargetingMotion()
00066 {
00067 }
00068 
00069 
00070 
00071 
00072 LLMotion::LLMotionInitStatus LLTargetingMotion::onInitialize(LLCharacter *character)
00073 {
00074         
00075         mCharacter = character;
00076 
00077         mPelvisJoint = mCharacter->getJoint("mPelvis");
00078         mTorsoJoint = mCharacter->getJoint("mTorso");
00079         mRightHandJoint = mCharacter->getJoint("mWristRight");
00080 
00081         
00082         if (!mPelvisJoint ||
00083                 !mTorsoJoint ||
00084                 !mRightHandJoint)
00085         {
00086                 llwarns << "Invalid skeleton for targeting motion!" << llendl;
00087                 return STATUS_FAILURE;
00088         }
00089 
00090         mTorsoState.setJoint( mTorsoJoint );
00091 
00092         
00093         mTorsoState.setUsage(LLJointState::ROT);
00094         addJointState( &mTorsoState );
00095 
00096         return STATUS_SUCCESS;
00097 }
00098 
00099 
00100 
00101 
00102 BOOL LLTargetingMotion::onActivate()
00103 {
00104         return TRUE;
00105 }
00106 
00107 
00108 
00109 
00110 BOOL LLTargetingMotion::onUpdate(F32 time, U8* joint_mask)
00111 {
00112         F32 slerp_amt = LLCriticalDamp::getInterpolant(TORSO_TARGET_HALF_LIFE);
00113 
00114         LLVector3 target;
00115         LLVector3* lookAtPoint = (LLVector3*)mCharacter->getAnimationData("LookAtPoint");
00116 
00117         BOOL result = TRUE;
00118 
00119         if (!lookAtPoint)
00120         {
00121                 return TRUE;
00122         }
00123         else
00124         {
00125                 target = *lookAtPoint;
00126                 target.normVec();
00127         }
00128         
00129         
00130         
00131 
00132         LLVector3 skyward(0.f, 0.f, 1.f);
00133         LLVector3 left(skyward % target);
00134         left.normVec();
00135         LLVector3 up(target % left);
00136         up.normVec();
00137         LLQuaternion target_aim_rot(target, left, up);
00138 
00139         LLQuaternion cur_torso_rot = mTorsoJoint->getWorldRotation();
00140 
00141         LLVector3 right_hand_at = LLVector3(0.f, -1.f, 0.f) * mRightHandJoint->getWorldRotation();
00142         left.setVec(skyward % right_hand_at);
00143         left.normVec();
00144         up.setVec(right_hand_at % left);
00145         up.normVec();
00146         LLQuaternion right_hand_rot(right_hand_at, left, up);
00147 
00148         LLQuaternion new_torso_rot = (cur_torso_rot * ~right_hand_rot) * target_aim_rot;
00149 
00150         
00151         new_torso_rot = new_torso_rot * ~cur_torso_rot;
00152 
00153         
00154         new_torso_rot = nlerp(slerp_amt, mTorsoState.getRotation(), new_torso_rot);
00155 
00156         
00157         LLQuaternion total_rot = new_torso_rot * mTorsoJoint->getRotation();
00158         total_rot.constrain(F_PI_BY_TWO * 0.8f);
00159         new_torso_rot = total_rot * ~mTorsoJoint->getRotation();
00160 
00161         mTorsoState.setRotation(new_torso_rot);
00162 
00163         return result;
00164 }
00165 
00166 
00167 
00168 
00169 void LLTargetingMotion::onDeactivate()
00170 {
00171 }
00172 
00173 
00174