llpose.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:16k
- /**
- * @file llpose.cpp
- * @brief Implementation of LLPose class.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2010, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- //-----------------------------------------------------------------------------
- // Header Files
- //-----------------------------------------------------------------------------
- #include "linden_common.h"
- #include "llpose.h"
- #include "llmotion.h"
- #include "llmath.h"
- #include "llstl.h"
- //-----------------------------------------------------------------------------
- // Static
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- // LLPose
- //-----------------------------------------------------------------------------
- LLPose::~LLPose()
- {
- }
- //-----------------------------------------------------------------------------
- // getFirstJointState()
- //-----------------------------------------------------------------------------
- LLJointState* LLPose::getFirstJointState()
- {
- mListIter = mJointMap.begin();
- if (mListIter == mJointMap.end())
- {
- return NULL;
- }
- else
- {
- return mListIter->second;
- }
- }
- //-----------------------------------------------------------------------------
- // getNextJointState()
- //-----------------------------------------------------------------------------
- LLJointState *LLPose::getNextJointState()
- {
- mListIter++;
- if (mListIter == mJointMap.end())
- {
- return NULL;
- }
- else
- {
- return mListIter->second;
- }
- }
- //-----------------------------------------------------------------------------
- // addJointState()
- //-----------------------------------------------------------------------------
- BOOL LLPose::addJointState(const LLPointer<LLJointState>& jointState)
- {
- if (mJointMap.find(jointState->getJoint()->getName()) == mJointMap.end())
- {
- mJointMap[jointState->getJoint()->getName()] = jointState;
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // removeJointState()
- //-----------------------------------------------------------------------------
- BOOL LLPose::removeJointState(const LLPointer<LLJointState>& jointState)
- {
- mJointMap.erase(jointState->getJoint()->getName());
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // removeAllJointStates()
- //-----------------------------------------------------------------------------
- BOOL LLPose::removeAllJointStates()
- {
- mJointMap.clear();
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // findJointState()
- //-----------------------------------------------------------------------------
- LLJointState* LLPose::findJointState(LLJoint *joint)
- {
- joint_map_iterator iter = mJointMap.find(joint->getName());
- if (iter == mJointMap.end())
- {
- return NULL;
- }
- else
- {
- return iter->second;
- }
- }
- //-----------------------------------------------------------------------------
- // findJointState()
- //-----------------------------------------------------------------------------
- LLJointState* LLPose::findJointState(const std::string &name)
- {
- joint_map_iterator iter = mJointMap.find(name);
- if (iter == mJointMap.end())
- {
- return NULL;
- }
- else
- {
- return iter->second;
- }
- }
- //-----------------------------------------------------------------------------
- // setWeight()
- //-----------------------------------------------------------------------------
- void LLPose::setWeight(F32 weight)
- {
- joint_map_iterator iter;
- for(iter = mJointMap.begin();
- iter != mJointMap.end();
- ++iter)
- {
- iter->second->setWeight(weight);
- }
- mWeight = weight;
- }
- //-----------------------------------------------------------------------------
- // getWeight()
- //-----------------------------------------------------------------------------
- F32 LLPose::getWeight() const
- {
- return mWeight;
- }
- //-----------------------------------------------------------------------------
- // getNumJointStates()
- //-----------------------------------------------------------------------------
- S32 LLPose::getNumJointStates() const
- {
- return (S32)mJointMap.size();
- }
- //-----------------------------------------------------------------------------
- // LLJointStateBlender
- //-----------------------------------------------------------------------------
- LLJointStateBlender::LLJointStateBlender()
- {
- for(S32 i = 0; i < JSB_NUM_JOINT_STATES; i++)
- {
- mJointStates[i] = NULL;
- mPriorities[i] = S32_MIN;
- mAdditiveBlends[i] = FALSE;
- }
- }
- LLJointStateBlender::~LLJointStateBlender()
- {
-
- }
- //-----------------------------------------------------------------------------
- // addJointState()
- //-----------------------------------------------------------------------------
- BOOL LLJointStateBlender::addJointState(const LLPointer<LLJointState>& joint_state, S32 priority, BOOL additive_blend)
- {
- llassert(joint_state);
- if (!joint_state->getJoint())
- // this joint state doesn't point to an actual joint, so we don't care about applying it
- return FALSE;
- for(S32 i = 0; i < JSB_NUM_JOINT_STATES; i++)
- {
- if (mJointStates[i].isNull())
- {
- mJointStates[i] = joint_state;
- mPriorities[i] = priority;
- mAdditiveBlends[i] = additive_blend;
- return TRUE;
- }
- else if (priority > mPriorities[i])
- {
- // we're at a higher priority than the current joint state in this slot
- // so shift everyone over
- // previous joint states (newer motions) with same priority should stay in place
- for (S32 j = JSB_NUM_JOINT_STATES - 1; j > i; j--)
- {
- mJointStates[j] = mJointStates[j - 1];
- mPriorities[j] = mPriorities[j - 1];
- mAdditiveBlends[j] = mAdditiveBlends[j - 1];
- }
- // now store ourselves in this slot
- mJointStates[i] = joint_state;
- mPriorities[i] = priority;
- mAdditiveBlends[i] = additive_blend;
- return TRUE;
- }
- }
- return FALSE;
- }
- //-----------------------------------------------------------------------------
- // blendJointStates()
- //-----------------------------------------------------------------------------
- void LLJointStateBlender::blendJointStates(BOOL apply_now)
- {
- // we need at least one joint to blend
- // if there is one, it will be in slot zero according to insertion logic
- // instead of resetting joint state to default, just leave it unchanged from last frame
- if (mJointStates[0].isNull())
- {
- return;
- }
- LLJoint* target_joint = apply_now ? mJointStates[0]->getJoint() : &mJointCache;
- const S32 POS_WEIGHT = 0;
- const S32 ROT_WEIGHT = 1;
- const S32 SCALE_WEIGHT = 2;
- F32 sum_weights[3];
- U32 sum_usage = 0;
- LLVector3 blended_pos = target_joint->getPosition();
- LLQuaternion blended_rot = target_joint->getRotation();
- LLVector3 blended_scale = target_joint->getScale();
- LLVector3 added_pos;
- LLQuaternion added_rot;
- LLVector3 added_scale;
- //S32 joint_state_index;
- sum_weights[POS_WEIGHT] = 0.f;
- sum_weights[ROT_WEIGHT] = 0.f;
- sum_weights[SCALE_WEIGHT] = 0.f;
- for(S32 joint_state_index = 0;
- joint_state_index < JSB_NUM_JOINT_STATES && mJointStates[joint_state_index].notNull();
- joint_state_index++)
- {
- LLJointState* jsp = mJointStates[joint_state_index];
- U32 current_usage = jsp->getUsage();
- F32 current_weight = jsp->getWeight();
- if (current_weight == 0.f)
- {
- continue;
- }
- if (mAdditiveBlends[joint_state_index])
- {
- if(current_usage & LLJointState::POS)
- {
- F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[POS_WEIGHT]);
- // add in pos for this jointstate modulated by weight
- added_pos += jsp->getPosition() * (new_weight_sum - sum_weights[POS_WEIGHT]);
- }
- 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]);
- }
- if (current_usage & LLJointState::ROT)
- {
- F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[ROT_WEIGHT]);
- // 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;
- }
- }
- else
- {
- // blend two jointstates together
-
- // blend position
- if(current_usage & LLJointState::POS)
- {
- if(sum_usage & LLJointState::POS)
- {
- F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[POS_WEIGHT]);
- // blend positions from both
- 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 = jsp->getPosition();
- sum_weights[POS_WEIGHT] = current_weight;
- }
- }
-
- // now do scale
- if(current_usage & LLJointState::SCALE)
- {
- if(sum_usage & LLJointState::SCALE)
- {
- F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[SCALE_WEIGHT]);
- // blend scales from both
- 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 = jsp->getScale();
- sum_weights[SCALE_WEIGHT] = current_weight;
- }
- }
- // rotation
- if (current_usage & LLJointState::ROT)
- {
- if(sum_usage & LLJointState::ROT)
- {
- 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, jsp->getRotation(), blended_rot);
- sum_weights[ROT_WEIGHT] = new_weight_sum;
- }
- else
- {
- // copy rotation from current
- blended_rot = jsp->getRotation();
- sum_weights[ROT_WEIGHT] = current_weight;
- }
- }
- // update resulting usage mask
- sum_usage = sum_usage | current_usage;
- }
- }
- if (!added_scale.isFinite())
- {
- added_scale.clearVec();
- }
- if (!blended_scale.isFinite())
- {
- blended_scale.setVec(1,1,1);
- }
- // apply transforms
- target_joint->setPosition(blended_pos + added_pos);
- target_joint->setScale(blended_scale + added_scale);
- target_joint->setRotation(added_rot * blended_rot);
- if (apply_now)
- {
- // now clear joint states
- for(S32 i = 0; i < JSB_NUM_JOINT_STATES; i++)
- {
- mJointStates[i] = NULL;
- }
- }
- }
- //-----------------------------------------------------------------------------
- // interpolate()
- //-----------------------------------------------------------------------------
- void LLJointStateBlender::interpolate(F32 u)
- {
- // only interpolate if we have a joint state
- if (!mJointStates[0])
- {
- return;
- }
- LLJoint* target_joint = mJointStates[0]->getJoint();
- if (!target_joint)
- {
- return;
- }
- target_joint->setPosition(lerp(target_joint->getPosition(), mJointCache.getPosition(), u));
- target_joint->setScale(lerp(target_joint->getScale(), mJointCache.getScale(), u));
- target_joint->setRotation(nlerp(u, target_joint->getRotation(), mJointCache.getRotation()));
- }
- //-----------------------------------------------------------------------------
- // clear()
- //-----------------------------------------------------------------------------
- void LLJointStateBlender::clear()
- {
- // now clear joint states
- for(S32 i = 0; i < JSB_NUM_JOINT_STATES; i++)
- {
- mJointStates[i] = NULL;
- }
- }
- //-----------------------------------------------------------------------------
- // resetCachedJoint()
- //-----------------------------------------------------------------------------
- void LLJointStateBlender::resetCachedJoint()
- {
- if (!mJointStates[0])
- {
- return;
- }
- LLJoint* source_joint = mJointStates[0]->getJoint();
- mJointCache.setPosition(source_joint->getPosition());
- mJointCache.setScale(source_joint->getScale());
- mJointCache.setRotation(source_joint->getRotation());
- }
- //-----------------------------------------------------------------------------
- // LLPoseBlender
- //-----------------------------------------------------------------------------
- LLPoseBlender::LLPoseBlender()
- : mNextPoseSlot(0)
- {
- }
- LLPoseBlender::~LLPoseBlender()
- {
- for_each(mJointStateBlenderPool.begin(), mJointStateBlenderPool.end(), DeletePairedPointer());
- }
- //-----------------------------------------------------------------------------
- // addMotion()
- //-----------------------------------------------------------------------------
- BOOL LLPoseBlender::addMotion(LLMotion* motion)
- {
- LLPose* pose = motion->getPose();
- for(LLJointState* jsp = pose->getFirstJointState(); jsp; jsp = pose->getNextJointState())
- {
- LLJoint *jointp = jsp->getJoint();
- LLJointStateBlender* joint_blender;
- if (mJointStateBlenderPool.find(jointp) == mJointStateBlenderPool.end())
- {
- // this is the first time we are animating this joint
- // so create new jointblender and add it to our pool
- joint_blender = new LLJointStateBlender();
- mJointStateBlenderPool[jointp] = joint_blender;
- }
- else
- {
- joint_blender = mJointStateBlenderPool[jointp];
- }
- if (jsp->getPriority() == LLJoint::USE_MOTION_PRIORITY)
- {
- joint_blender->addJointState(jsp, motion->getPriority(), motion->getBlendType() == LLMotion::ADDITIVE_BLEND);
- }
- else
- {
- joint_blender->addJointState(jsp, jsp->getPriority(), motion->getBlendType() == LLMotion::ADDITIVE_BLEND);
- }
- // add it to our list of active blenders
- if (std::find(mActiveBlenders.begin(), mActiveBlenders.end(), joint_blender) == mActiveBlenders.end())
- {
- mActiveBlenders.push_front(joint_blender);
- }
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // blendAndApply()
- //-----------------------------------------------------------------------------
- void LLPoseBlender::blendAndApply()
- {
- for (blender_list_t::iterator iter = mActiveBlenders.begin();
- iter != mActiveBlenders.end(); )
- {
- LLJointStateBlender* jsbp = *iter++;
- jsbp->blendJointStates();
- }
- // we're done now so there are no more active blenders for this frame
- mActiveBlenders.clear();
- }
- //-----------------------------------------------------------------------------
- // blendAndCache()
- //-----------------------------------------------------------------------------
- void LLPoseBlender::blendAndCache(BOOL reset_cached_joints)
- {
- for (blender_list_t::iterator iter = mActiveBlenders.begin();
- iter != mActiveBlenders.end(); ++iter)
- {
- LLJointStateBlender* jsbp = *iter;
- if (reset_cached_joints)
- {
- jsbp->resetCachedJoint();
- }
- jsbp->blendJointStates(FALSE);
- }
- }
- //-----------------------------------------------------------------------------
- // interpolate()
- //-----------------------------------------------------------------------------
- void LLPoseBlender::interpolate(F32 u)
- {
- for (blender_list_t::iterator iter = mActiveBlenders.begin();
- iter != mActiveBlenders.end(); ++iter)
- {
- LLJointStateBlender* jsbp = *iter;
- jsbp->interpolate(u);
- }
- }
- //-----------------------------------------------------------------------------
- // clearBlenders()
- //-----------------------------------------------------------------------------
- void LLPoseBlender::clearBlenders()
- {
- for (blender_list_t::iterator iter = mActiveBlenders.begin();
- iter != mActiveBlenders.end(); ++iter)
- {
- LLJointStateBlender* jsbp = *iter;
- jsbp->clear();
- }
- mActiveBlenders.clear();
- }