diff options
author | Monroe Williams <monroe@lindenlab.com> | 2007-08-02 01:18:34 +0000 |
---|---|---|
committer | Monroe Williams <monroe@lindenlab.com> | 2007-08-02 01:18:34 +0000 |
commit | 7138fb673ac3df46b9cb5f23d0d74e70fdd2b6b3 (patch) | |
tree | 3c34a3a180b5275bd4166b0056765c5868f56447 /indra/llcharacter | |
parent | f6a10b3214d79df4e8f5768acaa68edbd2de5620 (diff) |
Merge down from Branch_1-18-1:
svn merge --ignore-ancestry svn+ssh://svn.lindenlab.com/svn/linden/release@66449 svn+ssh://svn.lindenlab.com/svn/linden/branches/Branch_1-18-1@67131
Diffstat (limited to 'indra/llcharacter')
-rw-r--r-- | indra/llcharacter/llmotion.cpp | 11 | ||||
-rw-r--r-- | indra/llcharacter/llmotion.h | 8 | ||||
-rw-r--r-- | indra/llcharacter/llmotioncontroller.cpp | 157 | ||||
-rw-r--r-- | indra/llcharacter/llmotioncontroller.h | 15 | ||||
-rw-r--r-- | indra/llcharacter/llpose.cpp | 20 | ||||
-rw-r--r-- | indra/llcharacter/llpose.h | 2 |
6 files changed, 144 insertions, 69 deletions
diff --git a/indra/llcharacter/llmotion.cpp b/indra/llcharacter/llmotion.cpp index a53956223c..73aefa6640 100644 --- a/indra/llcharacter/llmotion.cpp +++ b/indra/llcharacter/llmotion.cpp @@ -106,6 +106,11 @@ void LLMotion::setDeactivateCallback( void (*cb)(void *), void* userdata ) mDeactivateCallbackUserData = userdata; } +BOOL LLMotion::isBlending() +{ + return mPose.getWeight() < 1.f; +} + //----------------------------------------------------------------------------- // activate() //----------------------------------------------------------------------------- @@ -122,10 +127,16 @@ void LLMotion::activate() void LLMotion::deactivate() { mActive = FALSE; + mPose.setWeight(0.f); if (mDeactivateCallback) (*mDeactivateCallback)(mDeactivateCallbackUserData); onDeactivate(); } +BOOL LLMotion::canDeprecate() +{ + return TRUE; +} + // End diff --git a/indra/llcharacter/llmotion.h b/indra/llcharacter/llmotion.h index 66882a2c11..77edba667f 100644 --- a/indra/llcharacter/llmotion.h +++ b/indra/llcharacter/llmotion.h @@ -79,13 +79,14 @@ public: void setStopped(BOOL stopped) { mStopped = stopped; } + BOOL isBlending(); + void activate(); void deactivate(); BOOL isActive() { return mActive; } - public: //------------------------------------------------------------------------- // animation callbacks to be implemented by subclasses @@ -125,6 +126,11 @@ public: // called when a motion is deactivated virtual void onDeactivate() = 0; + // can we crossfade this motion with a new instance when restarted? + // should ultimately always be TRUE, but lack of emote blending, etc + // requires this + virtual BOOL canDeprecate(); + // optional callback routine called when animation deactivated. void setDeactivateCallback( void (*cb)(void *), void* userdata ); diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index 592a6bae2c..bef5ea5dbb 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -174,34 +174,44 @@ void LLMotionController::deleteAllMotions() //----------------------------------------------------------------------------- void LLMotionController::addLoadedMotion(LLMotion* motionp) { + std::set<LLUUID> motions_to_kill; + + // gather all inactive, loaded motions if (mLoadedMotions.size() > MAX_MOTION_INSTANCES) { // too many motions active this frame, kill all blenders mPoseBlender.clearBlenders(); - for (U32 i = 0; i < mLoadedMotions.size(); i++) + for (motion_list_t::iterator loaded_motion_it = mLoadedMotions.begin(); + loaded_motion_it != mLoadedMotions.end(); + ++loaded_motion_it) { - LLMotion* cur_motionp = mLoadedMotions.front(); - mLoadedMotions.pop_front(); + LLMotion* cur_motionp = *loaded_motion_it; // motion isn't playing, delete it if (!isMotionActive(cur_motionp)) { - mCharacter->requestStopMotion(cur_motionp); - mAllMotions.erase(cur_motionp->getID()); - delete cur_motionp; - if (mLoadedMotions.size() <= MAX_MOTION_INSTANCES) - { - break; - } - } - else - { - // put active motion on back - mLoadedMotions.push_back(cur_motionp); + motions_to_kill.insert(cur_motionp->getID()); } } } + + // clean up all inactive, loaded motions + for (std::set<LLUUID>::iterator motion_it = motions_to_kill.begin(); + motion_it != motions_to_kill.end(); + ++motion_it) + { + // look up the motion again by ID to get canonical instance + // and kill it only if that one is inactive + LLUUID motion_id = *motion_it; + LLMotion* motionp = findMotion(motion_id); + if (motionp && !isMotionActive(motionp)) + { + removeMotion(motion_id); + } + } + + // add new motion to loaded list mLoadedMotions.push_back(motionp); } @@ -260,14 +270,24 @@ BOOL LLMotionController::addMotion( const LLUUID& id, LLMotionConstructor constr void LLMotionController::removeMotion( const LLUUID& id) { LLMotion* motionp = findMotion(id); + + removeMotionInstance(motionp); + + mAllMotions.erase(id); +} + +// removes instance of a motion from all runtime structures, but does +// not erase entry by ID, as this could be a duplicate instance +// use removeMotion(id) to remove all references to a given motion by id. +void LLMotionController::removeMotionInstance(LLMotion* motionp) +{ if (motionp) { - stopMotionLocally(id, TRUE); + stopMotionInstance(motionp, TRUE); mLoadingMotions.erase(motionp); mLoadedMotions.remove(motionp); mActiveMotions.remove(motionp); - mAllMotions.erase(id); delete motionp; } } @@ -328,28 +348,39 @@ LLMotion* LLMotionController::createMotion( const LLUUID &id ) //----------------------------------------------------------------------------- BOOL LLMotionController::startMotion(const LLUUID &id, F32 start_offset) { - // look for motion in our list of created motions - LLMotion *motion = createMotion(id); + // do we have an instance of this motion for this character? + LLMotion *motion = findMotion(id); + + // motion that is stopping will be allowed to stop but + // replaced by a new instance of that motion + if (motion + && motion->canDeprecate() + && motion->getFadeWeight() > 0.01f // not LOD-ed out + && (motion->isBlending() || motion->getStopTime() != 0.f)) + { + deprecateMotionInstance(motion); + // force creation of new instance + motion = NULL; + } + + // create new motion instance + if (!motion) + { + motion = createMotion(id); + } if (!motion) { return FALSE; } - //if the motion is already active, then we're done - else if (isMotionActive(motion)) // motion is playing and... + //if the motion is already active and allows deprecation, then let it keep playing + else if (motion->canDeprecate() && isMotionActive(motion)) { - if (motion->isStopped()) // motion has been stopped - { - deactivateMotion(motion, false); - } - else if (mTime < motion->mSendStopTimestamp) // motion is still active - { - return TRUE; - } + return TRUE; } // llinfos << "Starting motion " << name << llendl; - return activateMotion(motion, mTime - start_offset); + return activateMotionInstance(motion, mTime - start_offset); } @@ -360,6 +391,12 @@ BOOL LLMotionController::stopMotionLocally(const LLUUID &id, BOOL stop_immediate { // if already inactive, return false LLMotion *motion = findMotion(id); + + return stopMotionInstance(motion, stop_immediate); +} + +BOOL LLMotionController::stopMotionInstance(LLMotion* motion, BOOL stop_immediate) +{ if (!motion) { return FALSE; @@ -376,7 +413,7 @@ BOOL LLMotionController::stopMotionLocally(const LLUUID &id, BOOL stop_immediate if (stop_immediate) { - deactivateMotion(motion, false); + deactivateMotionInstance(motion); } return TRUE; } @@ -472,7 +509,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty { if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration()) { - deactivateMotion(motionp, false); + deactivateMotionInstance(motionp); } else if (motionp->isStopped() && mTime > motionp->getStopTime()) { @@ -490,7 +527,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty if (mLastTime <= motionp->mSendStopTimestamp) { mCharacter->requestStopMotion( motionp ); - stopMotionLocally(motionp->getID(), FALSE); + stopMotionInstance(motionp, FALSE); } } else if (mTime >= motionp->mActivationTimestamp) @@ -518,7 +555,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty if (mLastTime <= motionp->mSendStopTimestamp) { mCharacter->requestStopMotion( motionp ); - stopMotionLocally(motionp->getID(), FALSE); + stopMotionInstance(motionp, FALSE); } } @@ -526,7 +563,8 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty { if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration()) { - deactivateMotion(motionp, true); + posep->setWeight(0.f); + deactivateMotionInstance(motionp); } continue; } @@ -552,7 +590,8 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty } else { - deactivateMotion(motionp, true); + posep->setWeight(0.f); + deactivateMotionInstance(motionp); continue; } } @@ -597,7 +636,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty if (mLastTime <= motionp->mSendStopTimestamp) { mCharacter->requestStopMotion( motionp ); - stopMotionLocally(motionp->getID(), FALSE); + stopMotionInstance(motionp, FALSE); } } @@ -641,7 +680,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty // propagate this to the network // as not all viewers are guaranteed to have access to the same logic mCharacter->requestStopMotion( motionp ); - stopMotionLocally(motionp->getID(), FALSE); + stopMotionInstance(motionp, FALSE); } } @@ -713,7 +752,7 @@ void LLMotionController::updateMotion() // this motion should be playing if (!motionp->isStopped()) { - activateMotion(motionp, mTime); + activateMotionInstance(motionp, mTime); } } else if (status == LLMotion::STATUS_FAILURE) @@ -721,6 +760,7 @@ void LLMotionController::updateMotion() llinfos << "Motion " << motionp->getID() << " init failed." << llendl; sRegistry.markBad(motionp->getID()); mLoadingMotions.erase(curiter); + mAllMotions.erase(motionp->getID()); delete motionp; } @@ -753,9 +793,9 @@ void LLMotionController::updateMotion() //----------------------------------------------------------------------------- -// activateMotion() +// activateMotionInstance() //----------------------------------------------------------------------------- -BOOL LLMotionController::activateMotion(LLMotion *motion, F32 time) +BOOL LLMotionController::activateMotionInstance(LLMotion *motion, F32 time) { if (mLoadingMotions.find(motion) != mLoadingMotions.end()) { @@ -798,23 +838,38 @@ BOOL LLMotionController::activateMotion(LLMotion *motion, F32 time) } //----------------------------------------------------------------------------- -// deactivateMotion() +// deactivateMotionInstance() //----------------------------------------------------------------------------- -BOOL LLMotionController::deactivateMotion(LLMotion *motion, bool remove_weight) +BOOL LLMotionController::deactivateMotionInstance(LLMotion *motion) { - if( remove_weight ) + motion->deactivate(); + + motion_set_t::iterator found_it = mDeprecatedMotions.find(motion); + if (found_it != mDeprecatedMotions.end()) { - // immediately remove pose weighting instead of letting it time out - LLPose *posep = motion->getPose(); - posep->setWeight(0.f); + // deprecated motions need to be completely excised + removeMotionInstance(motion); + mDeprecatedMotions.erase(found_it); + } + else + { + // for motions that we are keeping, simply remove from active queue + mActiveMotions.remove(motion); } - - motion->deactivate(); - mActiveMotions.remove(motion); return TRUE; } +void LLMotionController::deprecateMotionInstance(LLMotion* motion) +{ + mDeprecatedMotions.insert(motion); + + //fade out deprecated motion + stopMotionInstance(motion, FALSE); + //no longer canonical + mAllMotions.erase(motion->getID()); +} + //----------------------------------------------------------------------------- // isMotionActive() //----------------------------------------------------------------------------- @@ -837,7 +892,7 @@ bool LLMotionController::isMotionLoading(LLMotion* motion) //----------------------------------------------------------------------------- LLMotion *LLMotionController::findMotion(const LLUUID& id) { - return mAllMotions[id]; + return get_if_there<LLUUID, LLMotion*>(mAllMotions, id, NULL); } //----------------------------------------------------------------------------- diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h index 19bab09a11..d5ea568479 100644 --- a/indra/llcharacter/llmotioncontroller.h +++ b/indra/llcharacter/llmotioncontroller.h @@ -159,16 +159,21 @@ public: LLMotion *findMotion( const LLUUID& id ); protected: + // internal operations act on motion instances directly + // as there can be duplicate motions per id during blending overlap void deleteAllMotions(); void addLoadedMotion(LLMotion *motion); - BOOL activateMotion(LLMotion *motion, F32 time); - BOOL deactivateMotion(LLMotion *motion, bool remove_weight); + BOOL activateMotionInstance(LLMotion *motion, F32 time); + BOOL deactivateMotionInstance(LLMotion *motion); + void deprecateMotionInstance(LLMotion* motion); + BOOL stopMotionInstance(LLMotion *motion, BOOL stop_imemdiate); + void removeMotionInstance(LLMotion* motion); void updateRegularMotions(); void updateAdditiveMotions(); void resetJointSignatures(); void updateMotionsByType(LLMotion::LLMotionBlendType motion_type); -protected: +protected: F32 mTimeFactor; static LLMotionRegistry sRegistry; LLPoseBlender mPoseBlender; @@ -183,11 +188,13 @@ protected: // Once an animations is loaded, it will be initialized and put on the mLoadedMotions deque. // Any animation that is currently playing also sits in the mActiveMotions list. - std::map<LLUUID, LLMotion*> mAllMotions; + typedef std::map<LLUUID, LLMotion*> motion_map_t; + motion_map_t mAllMotions; motion_set_t mLoadingMotions; motion_list_t mLoadedMotions; motion_list_t mActiveMotions; + motion_set_t mDeprecatedMotions; LLFrameTimer mTimer; F32 mTime; diff --git a/indra/llcharacter/llpose.cpp b/indra/llcharacter/llpose.cpp index e1b24d62cb..1f6d208b84 100644 --- a/indra/llcharacter/llpose.cpp +++ b/indra/llcharacter/llpose.cpp @@ -255,9 +255,9 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now) joint_state_index < JSB_NUM_JOINT_STATES && mJointStates[joint_state_index] != NULL; joint_state_index++) { - U32 current_usage = mJointStates[joint_state_index]->getUsage(); - F32 current_weight = mJointStates[joint_state_index]->getWeight(); LLJointState* jsp = mJointStates[joint_state_index]; + U32 current_usage = jsp->getUsage(); + F32 current_weight = jsp->getWeight(); if (current_weight == 0.f) { @@ -272,17 +272,14 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now) // add in pos for this jointstate modulated by weight added_pos += jsp->getPosition() * (new_weight_sum - sum_weights[POS_WEIGHT]); - //sum_weights[POS_WEIGHT] = new_weight_sum; } - // now do scale if(current_usage & LLJointState::SCALE) { F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[SCALE_WEIGHT]); // add in scale for this jointstate modulated by weight added_scale += jsp->getScale() * (new_weight_sum - sum_weights[SCALE_WEIGHT]); - //sum_weights[SCALE_WEIGHT] = new_weight_sum; } if (current_usage & LLJointState::ROT) @@ -291,7 +288,6 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now) // add in rotation for this jointstate modulated by weight added_rot = nlerp((new_weight_sum - sum_weights[ROT_WEIGHT]), added_rot, jsp->getRotation()) * added_rot; - //sum_weights[ROT_WEIGHT] = new_weight_sum; } } else @@ -306,13 +302,13 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now) F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[POS_WEIGHT]); // blend positions from both - blended_pos = lerp(mJointStates[joint_state_index]->getPosition(), blended_pos, sum_weights[POS_WEIGHT] / new_weight_sum); + blended_pos = lerp(jsp->getPosition(), blended_pos, sum_weights[POS_WEIGHT] / new_weight_sum); sum_weights[POS_WEIGHT] = new_weight_sum; } else { // copy position from current - blended_pos = mJointStates[joint_state_index]->getPosition(); + blended_pos = jsp->getPosition(); sum_weights[POS_WEIGHT] = current_weight; } } @@ -325,13 +321,13 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now) F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[SCALE_WEIGHT]); // blend scales from both - blended_scale = lerp(mJointStates[joint_state_index]->getScale(), blended_scale, sum_weights[SCALE_WEIGHT] / new_weight_sum); + blended_scale = lerp(jsp->getScale(), blended_scale, sum_weights[SCALE_WEIGHT] / new_weight_sum); sum_weights[SCALE_WEIGHT] = new_weight_sum; } else { // copy scale from current - blended_scale = mJointStates[joint_state_index]->getScale(); + blended_scale = jsp->getScale(); sum_weights[SCALE_WEIGHT] = current_weight; } } @@ -344,13 +340,13 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now) F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[ROT_WEIGHT]); // blend rotations from both - blended_rot = nlerp(sum_weights[ROT_WEIGHT] / new_weight_sum, mJointStates[joint_state_index]->getRotation(), blended_rot); + blended_rot = nlerp(sum_weights[ROT_WEIGHT] / new_weight_sum, jsp->getRotation(), blended_rot); sum_weights[ROT_WEIGHT] = new_weight_sum; } else { // copy rotation from current - blended_rot = mJointStates[joint_state_index]->getRotation(); + blended_rot = jsp->getRotation(); sum_weights[ROT_WEIGHT] = current_weight; } } diff --git a/indra/llcharacter/llpose.h b/indra/llcharacter/llpose.h index 5d17bd8458..b3cc994960 100644 --- a/indra/llcharacter/llpose.h +++ b/indra/llcharacter/llpose.h @@ -61,7 +61,7 @@ public: S32 getNumJointStates() const; }; -const S32 JSB_NUM_JOINT_STATES = 4; +const S32 JSB_NUM_JOINT_STATES = 6; class LLJointStateBlender { |