int CalCoreModel::loadCoreAnimation(const std::string& strFilename, const char* pbyBuffer, unsigned long nBufferSize) { // the core skeleton has to be loaded already if(m_pCoreSkeleton == 0) { CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__); return -1; } // load a new core animation CalLoader loader; CalCoreAnimation *pCoreAnimation; pCoreAnimation = loader.loadCoreAnimation(strFilename, pbyBuffer, nBufferSize); if(pCoreAnimation == 0) return -1; // add core animation to this core model int animationId; animationId = addCoreAnimation(pCoreAnimation); if(animationId == -1) { pCoreAnimation->release(); return -1; } return animationId; }
///////////////////////////////////// // Purpose: get the given anim's // duration // Output: none // Return: the duration ///////////////////////////////////// f32 IgfxObject::AnimGetDuration(s32 animID) { class CalCoreModel *pCalCoreModel = m_mdl->GetCalCoreModel(); if(!pCalCoreModel) return 0; CalCoreAnimation *pAnim = pCalCoreModel->getCoreAnimation(animID); if(pAnim) return pAnim->getDuration(); return 0; }
/// \brief Update function for the Cal3DModelManager /// Renders immediately, the queued list of renderobjects /// \return void void Cal3DModelManager::Update( DWORD tickCount ) { //check for bad callbacks stack< CalCoreAnimation * > deadCallbacks; CAL3DANIMATIONTOCALLBACKMAP::iterator iter = m_AnimationCallbacks.begin(); for(;iter != m_AnimationCallbacks.end(); ++iter) { Cal3dCallback * cb = (*iter).second; if( cb && cb->m_bDelete ) { deadCallbacks.push( (*iter).first ); } } //delete dead animation callbacks while( !deadCallbacks.empty() ) { CalCoreAnimation * ca = deadCallbacks.top(); deadCallbacks.pop(); iter = m_AnimationCallbacks.find( ca ); if( iter != m_AnimationCallbacks.end()) { Cal3dCallback * cb = (*iter).second; ca->removeCallback( cb ); delete cb; m_AnimationCallbacks.erase( iter); } } OBJECTLIST objList; static CHashString calTypeName( _T("Cal3DRenderObject")); //send a dummy file so we get a callback for this first phase IDTOOBJECTMAP::iterator objIter; IDTOOBJECTMAP *objMap = GetObjectMap( &calTypeName ); //update our objects if( objMap ) { IObject * destObject; for( objIter = objMap->begin();objIter != objMap->end(); ++objIter ) { destObject = objIter->second; destObject->Update(); } } }
CoreModel::~CoreModel() { if ( calCoreModel ) { // TODO: report CoreTrack memory leak problem to cal3d maintainers for ( int i = 0; i < calCoreModel->getCoreAnimationCount(); i++ ) { CalCoreAnimation* a = calCoreModel->getCoreAnimation( i ); std::list<CalCoreTrack *>& ct = a->getListCoreTrack(); for ( std::list<CalCoreTrack *>::iterator t = ct.begin(), tEnd = ct.end(); t != tEnd; ++t ) { (*t)->destroy(); delete (*t); } ct.clear(); } // cleanup of non-auto released resources delete calCoreModel; } }
DWORD Cal3DModelManager::OnGetCallback( DWORD size, void * params ) { GETCAL3DCALLBACK * msg; VERIFY_MESSAGE_SIZE( size, sizeof( GETCAL3DCALLBACK ) ); msg = (GETCAL3DCALLBACK*)params; if( msg && msg->anim ) { CAL3DANIMATIONTOCALLBACKMAP::iterator iter = m_AnimationCallbacks.find( msg->anim ); if( iter != m_AnimationCallbacks.end() ) { msg->instance = (*iter).second; }else { //create new instance Cal3dCallback * cb = new Cal3dCallback(); m_AnimationCallbacks.insert( pair< CalCoreAnimation *, Cal3dCallback * >( msg->anim, cb ) ); CalCoreAnimation * anim = msg->anim; anim->registerCallback( cb,0); msg->instance = cb; } return MSG_HANDLED_STOP; } return MSG_ERROR; }
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(); }