void CalMixer::applyBoneAdjustments() { CalSkeleton * pSkeleton = m_pModel->getSkeleton(); std::vector<CalBone *>& vectorBone = pSkeleton->getVectorBone(); unsigned int i; for( i = 0; i < m_numBoneAdjustments; i++ ) { CalMixerBoneAdjustmentAndBoneId * ba = & m_boneAdjustmentAndBoneIdArray[ i ]; CalBone * bo = vectorBone[ ba->boneId_ ]; CalCoreBone * cbo = bo->getCoreBone(); if( ba->boneAdjustment_.flags_ & CalMixerBoneAdjustmentFlagMeshScale ) { bo->setMeshScaleAbsolute( ba->boneAdjustment_.meshScaleAbsolute_ ); } if( ba->boneAdjustment_.flags_ & CalMixerBoneAdjustmentFlagPosRot ) { const CalVector & localPos = cbo->getTranslation(); CalVector adjustedLocalPos = localPos; CalQuaternion adjustedLocalOri = ba->boneAdjustment_.localOri_; static float const scale = 1.0f; float rampValue = ba->boneAdjustment_.rampValue_; static bool const replace = true; static float const unrampedWeight = 1.0f; bo->blendState( unrampedWeight, adjustedLocalPos, adjustedLocalOri, scale, replace, rampValue ); } } }
void CalMixer::updateSkeleton() { // get the skeleton we need to update CalSkeleton *pSkeleton; pSkeleton = m_pModel->getSkeleton(); if(pSkeleton == 0) return; // clear the skeleton state pSkeleton->clearState(); // get the bone vector of the skeleton std::vector<CalBone *>& vectorBone = pSkeleton->getVectorBone(); // The bone adjustments are "replace" so they have to go first, giving them // highest priority and full influence. Subsequent animations affecting the same bones, // including subsequent replace animations, will have their incluence attenuated appropriately. applyBoneAdjustments(); // loop through all animation actions std::list<CalAnimationAction *>::iterator itaa; for( itaa = m_listAnimationAction.begin(); itaa != m_listAnimationAction.end(); itaa++ ) { // get the core animation instance CalAnimationAction * aa = * itaa; // Manual animations can be on or off. If they are off, they do not apply // to the bone. if( aa->on() ) { CalCoreAnimation * pCoreAnimation = aa->getCoreAnimation(); // get the list of core tracks of above core animation std::list<CalCoreTrack *>& listCoreTrack = pCoreAnimation->getListCoreTrack(); // loop through all core tracks of the core animation std::list<CalCoreTrack *>::iterator itct; for( itct = listCoreTrack.begin(); itct != listCoreTrack.end(); itct++ ) { // get the appropriate bone of the track CalCoreTrack * ct = * itct; if( ct->getCoreBoneId() >= int(vectorBone.size()) ) { continue; } CalBone * pBone = vectorBone[ ct->getCoreBoneId() ]; // get the current translation and rotation CalVector translation; CalQuaternion rotation; ct->getState( aa->getTime(), translation, rotation); // Replace and CrossFade both blend with the replace function. bool replace = aa->getCompositionFunction() != CalAnimation::CompositionFunctionAverage; float scale = aa->getScale(); pBone->blendState( aa->getWeight(), translation, rotation, scale, replace, aa->getRampValue() ); } } } // === What does lockState() mean? Why do we need it at all? It seems only to allow us // to blend all the animation actions together into a temporary sum, and then // blend all the animation cycles together into a different sum, and then blend // the two sums together according to their relative weight sums. I believe this is mathematically // equivalent of blending all the animation actions and cycles together into a single sum, // according to their relative weights. pSkeleton->lockState(); // let the skeleton calculate its final state pSkeleton->calculateState(); }
void CalMixer::updateSkeleton() { // get the skeleton we need to update CalSkeleton *pSkeleton; pSkeleton = m_pModel->getSkeleton(); if(pSkeleton == 0) return; // clear the skeleton state pSkeleton->clearState(); // get the bone vector of the skeleton std::vector<CalBone *>& vectorBone = pSkeleton->getVectorBone(); // loop through all animation actions std::list<CalAnimationAction *>::iterator iteratorAnimationAction; for(iteratorAnimationAction = m_listAnimationAction.begin(); iteratorAnimationAction != m_listAnimationAction.end(); ++iteratorAnimationAction) { // get the core animation instance CalCoreAnimation *pCoreAnimation; pCoreAnimation = (*iteratorAnimationAction)->getCoreAnimation(); // Ask the animation for the pose at the given time std::vector<CalTransform> pose; pose.resize(pCoreAnimation->getTrackCount()); pCoreAnimation->getPose((*iteratorAnimationAction)->getTime(), pose); // Blend the pose into the current bone states for (unsigned bone_id = 0; bone_id < pSkeleton->getCoreSkeleton()->getVectorCoreBone().size(); ++bone_id) { int track_number = pCoreAnimation->getTrackAssignment(bone_id); // Skip this bone if the bone does not have a track assigned in the animation if (track_number == -1) { continue; } // Blend the animation pose with the skeleton CalBone* pBone = vectorBone[bone_id]; pBone->blendState((*iteratorAnimationAction)->getWeight(), pose[track_number].getTranslation(), pose[track_number].getRotation()); } } // lock the skeleton state pSkeleton->lockState(); // loop through all animation cycles std::list<CalAnimationCycle *>::iterator iteratorAnimationCycle; for(iteratorAnimationCycle = m_listAnimationCycle.begin(); iteratorAnimationCycle != m_listAnimationCycle.end(); ++iteratorAnimationCycle) { // get the core animation instance CalCoreAnimation *pCoreAnimation; pCoreAnimation = (*iteratorAnimationCycle)->getCoreAnimation(); // calculate adjusted time float animationTime; if((*iteratorAnimationCycle)->getState() == CalAnimation::STATE_SYNC) { if(m_animationDuration == 0.0f) { animationTime = 0.0f; } else { animationTime = m_animationTime * pCoreAnimation->getDuration() / m_animationDuration; } } else { animationTime = (*iteratorAnimationCycle)->getTime(); } // Ask the animation for the pose at the given time std::vector<CalTransform> pose; pose.resize(pCoreAnimation->getTrackCount()); pCoreAnimation->getPose(animationTime, pose); // Blend the pose into the current bone states for (unsigned index = 0; index < pose.size(); ++index) { int track_number = pCoreAnimation->getTrackAssignment(index); // Skip this bone if the bone does not have a track assigned in the animation if (track_number == -1) { continue; } CalBone* pBone = vectorBone[index]; pBone->blendState((*iteratorAnimationCycle)->getWeight(), pose[track_number].getTranslation(), pose[track_number].getRotation()); } } // lock the skeleton state pSkeleton->lockState(); // let the skeleton calculate its final state pSkeleton->calculateState(); }