osgAnimation 애니메이션 관리자

5299 단어 OSGosgAnimation
  • 간단한 소개


  • 이전 osgAnimation의 역할 대상에 대한 글에서 UpdateMatrixTransform 예시에서 우리는 UpdateCallback을 추가함으로써 애니메이션을 실현했다. 사실상 osgAnimation는 우리에게 기본적인 애니메이션 처리 클래스인 BasicAnimation Manager를 제공했다. 이 클래스는 NodeCallback에서 계승하여 여러 개의 애니메이션 대상의 관리를 맡았다. 이제 어떻게 실현되는지 살펴보자.
  • 애니메이션 관리자


  • 애니메이션 관리자에는 다음과 같은 몇 가지 종류가 있는데 그것이 바로 LinkVisitor,AnimationManagerBase,BasicAnimationManager이다. 다음은 이런 종류의 실현을 살펴보자.
  • LinkVisitor


  • Animation Manager Base에 사용되는 내부 보조 클래스는 하위 장면 아래의 역할 대상(Update Matrix Transform 등)을 훑어보는 데 사용된다. 우리는 개발 코드에서 이 클래스를 직접 사용하지 않는다. 다음은 이 클래스의 역할을 중점적으로 살펴본다. 코드는 다음과 같다.
    void LinkVisitor::apply(osg::Node& node)
    {
        osg::StateSet* st = node.getStateSet();
        if (st)
            handle_stateset(st);
    
        osg::NodeCallback* cb = node.getUpdateCallback();
        while (cb)
        {
            osgAnimation::AnimationUpdateCallbackBase* cba = dynamic_cast<osgAnimation::AnimationUpdateCallbackBase*>(cb);
            if (cba)
                link(cba);
            cb = cb->getNestedCallback();
        }
        traverse(node);
    }
    
    void LinkVisitor::apply(osg::Geode& node)
    {
        for (unsigned int i = 0; i < node.getNumDrawables(); i++)
        {
            osg::Drawable* drawable = node.getDrawable(i);
            if (drawable && drawable->getStateSet())
                handle_stateset(drawable->getStateSet());
        }
        apply(static_cast<osg::Node&>(node));
    }

    NodeVisitor는 NodeVisitor입니다. 이것은 우리가 그것이 작용 대상을 수집하는 데 사용되고, 작용 대상과Animation을 링크로 하는 것을 실현합니다. (실질적으로 채널과 작용 대상을 링크로 진행했습니다.) 즉 채널에서 연산 결과를 저장하는 데 사용되는 Target 대상을 작용 대상 중 그룹의 요소로 설정하는 Target (Stacked Transform Element의 target을 채널에 저장할 예정입니다)
  • AnimationManagerBase


  • AnimationManagerBase는 애니메이션 관리자의 기본 클래스로 애니메이션 관리자가 필요로 하는 기본 기능을 제공합니다. 이 클래스는 가상 기본 클래스이고 파생 클래스가 업데이트 구성원 함수를 실현해야 합니다.이 클래스는 NodeCallback이기 때문에 Operator () 조작부호를 다시 불러올 것입니다. 그 안에 무엇을 했는지 살펴보겠습니다.
    void AnimationManagerBase::operator()(osg::Node* node, osg::NodeVisitor* nv)
    {
        if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
        {
            if (needToLink())
            {
                link(node);
            }
            const osg::FrameStamp* fs = nv->getFrameStamp();
            update(fs->getSimulationTime());
        }
        traverse(node,nv);
    }
    osgAnimation의 작용 대상에서 UpdateMatrixTransform의 예를 비교해 보면 PlayCallback은 이런 종류와 유사하다는 것을 알 수 있다. 이 업데이트(fs->getsimulationTime() 호출은 전체Animation 애니메이션을 구동하고 전체 애니메이션을 한 프레임 한 프레임 움직이게 한다.
    또한 osgAnimation의 역할 대상에서 UpdateMatrixTransform의 예에서 PlayCallback을 애니메이션 서브 장면(구 노드)의 부모 노드로 설정하고 장면이 애니메이션 서브 노드에 이르기 전에 플레이Callback을 통해 애니메이션 서브 노드 위에 있는 MatrixTransform의 행렬 값을 업데이트하여 애니메이션 서브 장면을 두루 돌아다닐 때 서브 장면의 위치를 변동시키는 효과를 실현한다.같은 이치로 여기AnimationManagerBase도 이렇게 할 수 있겠지!맞아요, 바로 그렇습니다.위 코드에서 링크 (node) 는 이렇게 하는 것입니다. 실현을 살펴보겠습니다.
    void AnimationManagerBase::link(osg::Node* subgraph)
    {
        LinkVisitor* linker = getOrCreateLinkVisitor();
        linker->getAnimationList().clear();
        linker->getAnimationList() = _animations;
    
        subgraph->accept(*linker);
        _needToLink = false;
        buildTargetReference();
    }
    LinkVisitor를 통해 모든 StackedTransform Element의 Target를Channel에 설정하고 업데이트(fs->getsimulationTime())를 통해 모든 Channel의 Target 값을 업데이트합니다.업데이트 (fs->getsimulationTime ()) 가 도대체 무엇을 했는지 이어서 읽어 주십시오.
  • BasicAnimationManager


  • 이 클래스는 Animation ManagerBase 클래스를 통합하고 업데이트 방법을 다시 작성한 것입니다. 이것은 코드에서 가장 자주 사용하는 관리자 클래스입니다. 업데이트에서 무엇을 했는지 보십시오.
    void BasicAnimationManager::update (double time)
    {
        _lastUpdate = time; 
    
        for (TargetSet::iterator it = _targets.begin(); it != _targets.end(); ++it)
            (*it).get()->reset();
    
    // std::map , , 
        for( AnimationLayers::reverse_iterator iterAnim = _animationsPlaying.rbegin(); iterAnim != _animationsPlaying.rend(); ++iterAnim )
        {
            std::vector<int> toremove;
            int priority = iterAnim->first;
    		
            AnimationList& list = iterAnim->second;
            for (unsigned int i = 0; i < list.size(); i++)
            {
                if (! list[i]->update(time, priority))
                {
                    toremove.push_back(i);
                } 
            }
            while (!toremove.empty())
            {
                list.erase(list.begin() + toremove.back());
                toremove.pop_back();
            }
        }
    }
    여기의AnimationLayers는 이렇게 정의합니다. typedef std::mapAnimationLayers;이것은 std::map입니다. 첫 번째 요소는 우선순위를 대표합니다. 즉, Target의 데이터를 업데이트할 때 우선순위에 따라 높은 것에서 낮은 것으로 진행됩니다.osgAnimation의 역할 대상 중 UpdateMatrixTransform의 예에서 우리는 단지 하나의 Animation 대상을 업데이트했을 뿐이다. 여기는 여러 개가 업데이트되었지만 원리는 모두 유사하다.
  • 총결산


  • 상술한 분석을 결합하여 우리는 관리자가 하는 일은 실제적으로 업데이트 리셋 구동 데이터를 사용하여 업데이트를 완성하는 것임을 알았다.다음과 같은 절차가 필요합니다.
    1. 장면에서의 작용 대상(UpdateMatrixTransform)의 요소(즉 StackedTransformElement)의Target를Channel에 설정하여Target가 데이터를 전송하는 유대를 구축한다.이 절차는 LinkVisitor를 통해 수행됩니다.
    2. 리셋 중 업데이트의 호출을 업데이트합니다. 이 업데이트의 호출은 일련의 연쇄 반응을 일으켜 Animation의 모든 채널의 업데이트를 한 번 호출합니다. 실질적으로 채널에 있는 모든 Target의 업데이트를 호출하여 데이터의 업데이트를 완성합니다. 이 과정은 BasicAnimationManager의 업데이트에서 완성됩니다.
    이 수업의 인스턴스는 osg Examples의 osganimationsolid 예를 참조하십시오.

    좋은 웹페이지 즐겨찾기