diff options
Diffstat (limited to 'indra/llcharacter/lltargetingmotion.cpp')
-rw-r--r-- | indra/llcharacter/lltargetingmotion.cpp | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/indra/llcharacter/lltargetingmotion.cpp b/indra/llcharacter/lltargetingmotion.cpp new file mode 100644 index 0000000000..0f3eaa855b --- /dev/null +++ b/indra/llcharacter/lltargetingmotion.cpp @@ -0,0 +1,151 @@ +/** + * @file lltargetingmotion.cpp + * @brief Implementation of LLTargetingMotion class. + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "linden_common.h" + +#include "lltargetingmotion.h" +#include "llcharacter.h" +#include "v3dmath.h" +#include "llcriticaldamp.h" + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- +const F32 TORSO_TARGET_HALF_LIFE = 0.25f; +const F32 MAX_TIME_DELTA = 2.f; //max two seconds a frame for calculating interpolation +const F32 TARGET_PLANE_THRESHOLD_DOT = 0.6f; +const F32 TORSO_ROT_FRACTION = 0.5f; + +//----------------------------------------------------------------------------- +// LLTargetingMotion() +// Class Constructor +//----------------------------------------------------------------------------- +LLTargetingMotion::LLTargetingMotion(const LLUUID &id) : LLMotion(id) +{ + mCharacter = NULL; + mName = "targeting"; +} + + +//----------------------------------------------------------------------------- +// ~LLTargetingMotion() +// Class Destructor +//----------------------------------------------------------------------------- +LLTargetingMotion::~LLTargetingMotion() +{ +} + +//----------------------------------------------------------------------------- +// LLTargetingMotion::onInitialize(LLCharacter *character) +//----------------------------------------------------------------------------- +LLMotion::LLMotionInitStatus LLTargetingMotion::onInitialize(LLCharacter *character) +{ + // save character for future use + mCharacter = character; + + mPelvisJoint = mCharacter->getJoint("mPelvis"); + mTorsoJoint = mCharacter->getJoint("mTorso"); + mRightHandJoint = mCharacter->getJoint("mWristRight"); + + // make sure character skeleton is copacetic + if (!mPelvisJoint || + !mTorsoJoint || + !mRightHandJoint) + { + llwarns << "Invalid skeleton for targeting motion!" << llendl; + return STATUS_FAILURE; + } + + mTorsoState.setJoint( mTorsoJoint ); + + // add joint states to the pose + mTorsoState.setUsage(LLJointState::ROT); + addJointState( &mTorsoState ); + + return STATUS_SUCCESS; +} + +//----------------------------------------------------------------------------- +// LLTargetingMotion::onActivate() +//----------------------------------------------------------------------------- +BOOL LLTargetingMotion::onActivate() +{ + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLTargetingMotion::onUpdate() +//----------------------------------------------------------------------------- +BOOL LLTargetingMotion::onUpdate(F32 time, U8* joint_mask) +{ + F32 slerp_amt = LLCriticalDamp::getInterpolant(TORSO_TARGET_HALF_LIFE); + + LLVector3 target; + LLVector3* lookAtPoint = (LLVector3*)mCharacter->getAnimationData("LookAtPoint"); + + BOOL result = TRUE; + + if (!lookAtPoint) + { + return TRUE; + } + else + { + target = *lookAtPoint; + target.normVec(); + } + + //LLVector3 target_plane_normal = LLVector3(1.f, 0.f, 0.f) * mPelvisJoint->getWorldRotation(); + //LLVector3 torso_dir = LLVector3(1.f, 0.f, 0.f) * (mTorsoJoint->getWorldRotation() * mTorsoState.getRotation()); + + LLVector3 skyward(0.f, 0.f, 1.f); + LLVector3 left(skyward % target); + left.normVec(); + LLVector3 up(target % left); + up.normVec(); + LLQuaternion target_aim_rot(target, left, up); + + LLQuaternion cur_torso_rot = mTorsoJoint->getWorldRotation(); + + LLVector3 right_hand_at = LLVector3(0.f, -1.f, 0.f) * mRightHandJoint->getWorldRotation(); + left.setVec(skyward % right_hand_at); + left.normVec(); + up.setVec(right_hand_at % left); + up.normVec(); + LLQuaternion right_hand_rot(right_hand_at, left, up); + + LLQuaternion new_torso_rot = (cur_torso_rot * ~right_hand_rot) * target_aim_rot; + + // find ideal additive rotation to make torso point in correct direction + new_torso_rot = new_torso_rot * ~cur_torso_rot; + + // slerp from current additive rotation to ideal additive rotation + new_torso_rot = nlerp(slerp_amt, mTorsoState.getRotation(), new_torso_rot); + + // constraint overall torso rotation + LLQuaternion total_rot = new_torso_rot * mTorsoJoint->getRotation(); + total_rot.constrain(F_PI_BY_TWO * 0.8f); + new_torso_rot = total_rot * ~mTorsoJoint->getRotation(); + + mTorsoState.setRotation(new_torso_rot); + + return result; +} + +//----------------------------------------------------------------------------- +// LLTargetingMotion::onDeactivate() +//----------------------------------------------------------------------------- +void LLTargetingMotion::onDeactivate() +{ +} + + +// End |