查看: 1799|回复: 7

osgAnimation更新回调 与 MFC-Ontimer

[复制链接]

该用户从未签到

发表于 2010-12-10 22:11:39 | 显示全部楼层 |阅读模式
我是新手,请大家指点!谢谢!

程序的基本思路和现在的问题是:
用MFC+OSG实现一个动画。在MFC中有个ONTIMER事件实时刷新一些全局变量。然后希望在OSG中能根据这些全局的值实时更新动画。
现在碰到的问题是:
ONTIMER事件中,这些全局变量的数据实时刷新了。
但是OSG中只是第一次初始化后时,把这些全局变量的当前数据读进来,循环进行动画。后面没有按这些全局变量的实时值进行更新。更新回调没起作用。

请各位大侠,ARRAY老师指导!该如何修改。

源码: OSG.CPP ..............................................

double YawAngle[3];
double PitchAngle1[3];
double PitchAngle2[3];
double PitchAngle3[3];
double RotateAngle[3];
double f = 1.0; //给定数据的赫兹
void createEuler0Keyframes(osgAnimation:uatKeyframeContainer* kc)   // yaw
{ //给定数据
for(int i=0;i<3;i++)
{  kc->push_back(osgAnimation::QuatKeyframe((float)(i*f),osg::Quat(osg:egreesToRadians(YawAngle[i]),osg::Vec3d(0.,0.,1.)))); }  
}
void createEuler1Keyframes(osgAnimation::QuatKeyframeContainer* kc)  //Rotating
{
//给定数据
for (int i=0;i<3;i++)
{  kc->push_back(osgAnimation::QuatKeyframe((float)(i*f),osg::Quat(osg::DegreesToRadians(RotateAngle[i]),osg::Vec3d(0.,1.,0.)))); }
}
void createEuler2Keyframes(osgAnimation::QuatKeyframeContainer* kc) //PitchAngle1 - Red
{
//给定数据
for(int i=0;i<3;i++)
{  kc->push_back(osgAnimation::QuatKeyframe((float)(i*f),osg::Quat(osg::DegreesToRadians(PitchAngle1[i]),osg::Vec3d(0.,0.,1.)))); }
}
void createEuler3Keyframes(osgAnimation::QuatKeyframeContainer* kc) //PitchAngle2 - Green
{
//给定数据
    for(int i=0;i<3;i++)
{  kc->push_back(osgAnimation::QuatKeyframe((float)(i*f),osg::Quat(osg::DegreesToRadians(PitchAngle2[i]),osg::Vec3d(0.866,0.,-0.5)))); }
}
void createEuler4Keyframes(osgAnimation::QuatKeyframeContainer* kc)  //PitchAngle3 - Blue
{
//给定数据
    for(int i=0;i<3;i++)
{  kc->push_back(osgAnimation::QuatKeyframe((float)(i*f),osg::Quat(osg::DegreesToRadians(PitchAngle3[i]),osg::Vec3d(-0.866,0.,-0.5)))); }
}
void createPosition0Keyframes(osgAnimation::Vec3KeyframeContainer* kc)
{
//给定数据
    float position[8]={-487.,-487.,-487.,-487.,-487.,-487.,-487.,-487.};
for(int i=0;i<=7;i++)
{  kc->push_back(osgAnimation::Vec3Keyframe((float)(i/f),osg::Vec3(0.,position[i],0.))); }
}
void createPosition1Keyframes(osgAnimation::Vec3KeyframeContainer* kc)
{
//给定数据
    float position[8]={-487.,-487.,-487.,-487.,-487.,-487.,-487.,-487.};
for(int i=0;i<=7;i++)
{  kc->push_back(osgAnimation::Vec3Keyframe((float)(i/f),osg::Vec3(0.,position[i],0.))); }
}
void createPosition2Keyframes(osgAnimation::Vec3KeyframeContainer* kc)
{
//给定数据
    float position[8]={-487.,-487.,-487.,-487.,-487.,-487.,-487.,-487.};
for(int i=0;i<=7;i++)
{  kc->push_back(osgAnimation::Vec3Keyframe((float)(i/f),osg::Vec3(0.,position[i],0.))); }
}

cOSG::cOSG(HWND hWnd) :
   m_hWnd(hWnd), mDone(false)
{  }

cOSG::~cOSG()
{}

void cOSG::InitOSG(std::string modelname)
{
    //存储加载模型的文件名
m_ModelName = modelname;
    // 初始化osg
    InitManipulators();
    InitSceneGraph();
    InitCameraConfig();
}
void cOSG::InitManipulators(void)
{
    // 创建一个追踪求操作器
    trackball = new osgGA::TrackballManipulator();
    //创建一个调度操作器
    keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
    // 添加追踪球操作器到调度操作器中
    keyswitchManipulator->addMatrixManipulator( '1', "Trackball", trackball.get());
    // Init the switcher to the first manipulator (in this case the only manipulator)
    keyswitchManipulator->selectMatrixManipulator(0);  // Zero based index Value
}

void cOSG::InitSceneGraph(void)
{
    // 定义主节点
    mRoot  = new osg::Group;
    // 加载模型
    mModel = osgDB::readNodeFile(m_ModelName);
fan120 = osgDB::readNodeFile("fan120.osg");
    fan240 = osgDB::readNodeFile("fan240.osg");
exis = osgDB::readNodeFile("exis.osg");
engineroom = osgDB::readNodeFile("engineroom.osg");
tower = osgDB::readNodeFile("tower.osg");
   //优化模型
    osgUtil::Optimizer optimizer;
optimizer.optimize(mModel.get());
optimizer.optimize(fan120.get());
optimizer.optimize(fan240.get());
optimizer.optimize(exis.get());
optimizer.optimize(engineroom.get());
optimizer.optimize(tower.get());
    optimizer.reset();
    //添加模型到场景中
    mRoot->addChild(mModel.get());
}
void cOSG::InitCameraConfig(void)
{
    // Local Variable to hold window size data
    RECT rect;
    // 创建一个视图
    mViewer = new osgViewer::Viewer();
    // Add a Stats Handler to the viewer
    mViewer->addEventHandler(new osgViewer::StatsHandler);
   
    // Get the current window size
    ::GetWindowRect(m_hWnd, &rect);
    // Init the GraphicsContext Traits
    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
    // Init the Windata Variable that holds the handle for the Window to display OSG in.
    osg::ref_ptr<osg::Referenced> windata = new osgViewer::GraphicsWindowWin32::WindowData(m_hWnd);
    // Setup the traits parameters
    traits->x = 0;
    traits->y = 0;
    traits->width = rect.right - rect.left;
    traits->height = rect.bottom - rect.top;
    traits->windowDecoration = false;
    traits->doubleBuffer = true;
    traits->sharedContext = 0;
    traits->setInheritedWindowPixelFormat = true;
    traits->inheritedWindowData = windata;
    // Create the Graphics Context
    osg::GraphicsContext* gc = osg::GraphicsContext::createGraphicsContext(traits.get());
    // Init a new Camera (Master for this View)
    osg::ref_ptr<osg::Camera> camera = new osg::Camera;
    // Assign Graphics Context to the Camera
    camera->setGraphicsContext(gc);
    // Set the viewport for the Camera
    camera->setViewport(new osg::Viewport(traits->x, traits->y, traits->width, traits->height));
    //  camera->setViewport(new osg::Viewport(8, 61, 251, 338));
    // Add the Camera to the Viewer
    mViewer->addSlave(camera.get());

    // Add the Camera Manipulator to the Viewer
    mViewer->setCameraManipulator(keyswitchManipulator.get());
    osg::ref_ptr<osgAnimation::Skeleton> skelroot=new osgAnimation::Skeleton;
skelroot->setDataVariance(osg::Object::DYNAMIC);
skelroot->setDefaultUpdateCallback();
osg::ref_ptr<osgAnimation::Bone> bone0=new osgAnimation::Bone;
{
  bone0->setDataVariance(osg::Object::DYNAMIC);
  bone0->setName("bone0");
  bone0->addChild(engineroom);
  bone0->setDefaultUpdateCallback();
}
osg::ref_ptr<osgAnimation::Bone> bone1=new osgAnimation::Bone;
{
  bone1->setDataVariance(osg::Object::DYNAMIC);
  bone1->setName("bone1");
  bone1->addChild(exis);
  bone1->setDefaultUpdateCallback();
}
osg::ref_ptr<osgAnimation::Bone> bone2=new osgAnimation::Bone;
{
  bone2->setDataVariance(osg::Object::DYNAMIC);
  bone2->setName("bone2");
  bone2->addChild(mRoot);
  bone2->setDefaultUpdateCallback();
}

osg::ref_ptr<osgAnimation::Bone> bone3=new osgAnimation::Bone;
{
  bone3->setDataVariance(osg::Object::DYNAMIC);
  bone3->setName("bone3");
  bone3->addChild(fan120);
  bone3->setDefaultUpdateCallback();
}
osg::ref_ptr<osgAnimation::Bone> bone4=new osgAnimation::Bone;
{
  bone4->setDataVariance(osg::Object::DYNAMIC);
  bone4->setName("bone4");
  bone4->addChild(fan240);
  bone4->setDefaultUpdateCallback();
}
skelroot->addChild(bone0);
bone0->addChild(bone1);
bone1->addChild(bone2);
bone1->addChild(bone3);
bone1->addChild(bone4);
/////////////////////////////

osg::ref_ptr<osg::Group> scene = new osg::Group();
osg::ref_ptr<osgAnimation::BasicAnimationManager> mnt=new osgAnimation::BasicAnimationManager;
scene->setUpdateCallback(mnt);
scene->addChild(skelroot);
scene->addChild(tower);
osg::ref_ptr<osgAnimation::Animation> anim=new osgAnimation::Animation;
{
  //anim->setStartTime(2.0);
  anim->setDataVariance(osg::Object::DYNAMIC);
  
  osg::ref_ptr<osgAnimation::QuatSphericalLinearChannel> ch0=new osgAnimation::QuatSphericalLinearChannel;
  ch0->setName("quaternion");
  ch0->setTargetName("bone0");
  createEuler0Keyframes(ch0->getOrCreateSampler()->getOrCreateKeyframeContainer());

  osg::ref_ptr<osgAnimation::QuatSphericalLinearChannel> ch1=new osgAnimation::QuatSphericalLinearChannel;
  ch1->setName("quaternion");
  ch1->setTargetName("bone1");
  createEuler1Keyframes(ch1->getOrCreateSampler()->getOrCreateKeyframeContainer());   
  osg::ref_ptr<osgAnimation::QuatSphericalLinearChannel> ch2=new osgAnimation::QuatSphericalLinearChannel;
  ch2->setName("quaternion");
  ch2->setTargetName("bone2");
  createEuler2Keyframes(ch2->getOrCreateSampler()->getOrCreateKeyframeContainer());
  osg::ref_ptr<osgAnimation::Vec3LinearChannel> ch5=new osgAnimation::Vec3LinearChannel;
  ch5->setName("position");
  ch5->setTargetName("bone2");
  createPosition0Keyframes(ch5->getOrCreateSampler()->getOrCreateKeyframeContainer());
  osg::ref_ptr<osgAnimation::QuatSphericalLinearChannel> ch3=new osgAnimation::QuatSphericalLinearChannel;
  ch3->setName("quaternion");
  ch3->setTargetName("bone3");
  createEuler3Keyframes(ch3->getOrCreateSampler()->getOrCreateKeyframeContainer());
  osg::ref_ptr<osgAnimation::Vec3LinearChannel> ch6=new osgAnimation::Vec3LinearChannel;
  ch6->setName("position");
  ch6->setTargetName("bone3");
  createPosition1Keyframes(ch6->getOrCreateSampler()->getOrCreateKeyframeContainer());
  osg::ref_ptr<osgAnimation::QuatSphericalLinearChannel> ch4=new osgAnimation::QuatSphericalLinearChannel;
  ch4->setName("quaternion");
  ch4->setTargetName("bone4");
  createEuler4Keyframes(ch4->getOrCreateSampler()->getOrCreateKeyframeContainer());
  osg::ref_ptr<osgAnimation::Vec3LinearChannel> ch7=new osgAnimation::Vec3LinearChannel;
  ch7->setName("position");
  ch7->setTargetName("bone4");
  createPosition0Keyframes(ch7->getOrCreateSampler()->getOrCreateKeyframeContainer());
  anim->addChannel(ch0);
  anim->addChannel(ch1);
  anim->addChannel(ch2);
  anim->addChannel(ch3);
  anim->addChannel(ch4);
  anim->addChannel(ch5);
  anim->addChannel(ch6);
  anim->addChannel(ch7);

}
mnt->registerAnimation(anim);
//mnt->buildTargetReference();
mnt->playAnimation(anim);

/////////////
//osgUtil::Optimizer optimizer ;
//optimizer.optimize(scene);
mViewer->setSceneData(scene);
    mViewer->realize();
//mViewer->run();
/*while (!mViewer->done())
    {
        mViewer->frame();
    } */
}
void cOSG:reFrameUpdate()
{
    // Due any preframe updates in this routine
}
void cOSG::PostFrameUpdate()
{
    // Due any postframe updates in this routine
}
void cOSG::Render(void* ptr)
{
cOSG* osg = (cOSG*)ptr;
    osgViewer::Viewer* viewer = osg->getViewer();
    viewer->run();
    AfxMessageBox((LPCTSTR)"Exit Rendering Thread");
    _endthread();
}


源码:COsgMFCSDIView.CPP.................................................

extern double YawAngle[3];
extern double PitchAngle1[3];
extern double PitchAngle1[3];
extern double PitchAngle2[3];
extern double PitchAngle3[3];
extern double RotateAngle[3];

void COsgMFCSDIView::OnInitialUpdate()
{
             CView::OnInitialUpdate();

                CString csFileName("fan0.osg");
        char buf[100];
        USES_CONVERSION;
        strcpy(buf,csFileName);
        std::string std_Name = buf;//CString 转  std::string  不支持有中文文件夹
        if(std_Name.length())
        {
                mOSG->InitOSG(std_Name);
                mThreadHandle = (HANDLE)_beginthread(&cOSG::Render, 0, mOSG);
                }
               SetTimer(0,1000,NULL);
}

void COsgMFCSDIView::OnTimer(UINT_PTR nIDEvent)
{
        // TODO: Add your message handler code here and/or call default
        YawAngle[0] = YawAngle[1];
        YawAngle[1] = YawAngle[2];
        YawAngle[2] = YawAngle[2] + 10.0;
        if (YawAngle[2] > 180)
        {YawAngle[2] = 0;        }

        RotateAngle[0] = RotateAngle[1];
        RotateAngle[1] = RotateAngle[2];
        RotateAngle[2] = RotateAngle[2] + 10.0;
        if (RotateAngle[2] > 360)
        {RotateAngle[2] = 0;        }

        PitchAngle1[0] = PitchAngle1[1];
        PitchAngle1[1] = PitchAngle1[2];
        PitchAngle1[2] = PitchAngle1[2] + 10.0;
        if (PitchAngle1[2] > 90)
        {PitchAngle1[2] = 0;}

        PitchAngle2[0] = PitchAngle2[1];
        PitchAngle2[1] = PitchAngle2[2];
        PitchAngle2[2] = PitchAngle2[2] + 10.0;
        if (PitchAngle2[2] > 90)
        {PitchAngle2[2] = 0;}

        PitchAngle3[0] = PitchAngle3[1];
        PitchAngle3[1] = PitchAngle3[2];
        PitchAngle3[2] = PitchAngle3[2] + 10.0;
        if (PitchAngle3[2] > 90)
        {PitchAngle3[2] = 0;}
        CView::OnTimer(nIDEvent);
}

该用户从未签到

发表于 2010-12-13 08:47:53 | 显示全部楼层
您修改了PitchAngle这些全局量之后,在什么地方将它们传递给动画回调了?

该用户从未签到

 楼主| 发表于 2010-12-13 13:31:15 | 显示全部楼层
本帖最后由 osghaha 于 2010-12-13 15:33 编辑

在Keyframe数据里用到了这些全局变量。
然后用BasicAnimationManager来进行动画管理。

但实话说,我也不知道怎么做更新回调。
还望指导!

该用户从未签到

发表于 2010-12-13 15:49:01 | 显示全部楼层
这是一个很基本的C++的概念了,传值不等于传址,举个最简单的例子:
int a = 10;
int b = a;
这之后无论a如何变化,都不会影响到b。这里也是这个道理:您把PitchAngle的内容赋予keyContainer之后,这两者就不再有关系,无论您以后如何改变PitchAngle的值,都不会对别的对象有所影响,除非您再次把全局量的值设置给它们

该用户从未签到

 楼主| 发表于 2010-12-13 16:08:02 | 显示全部楼层
“传值和地址的概念”,这个我了解的。

我需要解决的问题其实就是您说的问题:怎么“再次把全局量的值设置给它们”?

请ARRAY老师指导,谢谢!

该用户从未签到

发表于 2010-12-14 08:32:12 | 显示全部楼层
您需要重新构建KeyframeContainer并将它们传递给Channel

该用户从未签到

 楼主| 发表于 2010-12-14 11:44:09 | 显示全部楼层
还是不知道怎么弄。
在哪段代码进行更新呢?放到哪里呢?
您看我的代码,然后给我些具体的指导吗。谢谢了!

该用户从未签到

发表于 2010-12-14 16:25:01 | 显示全部楼层
大体说来就是建立一个新的更新回调,然后在其中修改关键帧信息,您的修改信息需要传递给更新回调才可以
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表