OpenSceneGraph将相机设置在初始位置

时间:2014-01-17 07:23:06

标签: c++ opengl camera openscenegraph

我是第一次使用OpenSceneGraph而且我有点迷失,因为文档真的不那么清楚......

所以,我有这个代码加载带有房子的obj文件,我已经淹没了一个小盒子,我想要“人”。所以现在,我不想在那里放置那个盒子,我想把相机放在那里,看着前面,后来我会去固定相机周围的地形,这样看起来就像相机在移动但是地形在移动。

所以,这是我的代码:

int main()
{
    osgViewer::Viewer viewer;

    viewer.setUpViewInWindow(0,0,800,800);

    osg::ref_ptr<osg::Group> root (new osg::Group);

    osg::Node* terrain = osgDB::readNodeFile(".terrain.obj");
    if(terrain == NULL) {
        return -1;
    }

    Geode* gbox = new Geode();
    gbox->addDrawable(new ShapeDrawable(new Box()));

    PositionAttitudeTransform* terrainT = new PositionAttitudeTransform();

    PositionAttitudeTransform* boxT = new PositionAttitudeTransform();
    boxT->setScale(Vec3d(50,50,50));
    boxT->setPosition(Vec3d(1000,1000,0)); 

    root->addChild(terrainT);
    root->addChild(boxT);
    terrainT->addChild(terrain);
    boxT->addChild(gbox);

    viewer.setSceneData( root.get() ); 
    viewer.addEventHandler(new osgViewer::WindowSizeHandler);
    viewer.setCameraManipulator(new osgGA::TrackballManipulator());

    viewer.realize();
    while(!viewer.done()) {
        viewer.frame(); 
    }

    return 0;
}

所以这段代码可以正常运行,它可以正确加载场景,将盒子放在我想要的位置,然后用鼠标导航。

现在,我真的找不到把相机放在盒子里面的东西。我不能。

任何人都可以给我一些如何做的提示吗?它应该不是很难,但是我找不到任何好的教程,而且Viewer和Camera类的文档实际上没什么用处。

1 个答案:

答案 0 :(得分:7)

几点说明:

  • 尝试并提供OSG附带的模型示例
  • 加入构建代码所需的所有标题,这会让那些试图帮助您的人更快:)
  • 你的代码整洁干净,这是件好事!

现在,与OSG有关:

  • OSG使用它自己的智能指针实现,即osg::ref_ptr。每次创建一个继承自osg::Referenced的新OSG对象时都必须使用它,其中包含几乎所有内容。您在创建root节点时使用过一次,这很好,但由于您创建的所有其他OSG对象的析构函数都是私有的,因此它们会造成内存泄漏。当然,这对于这个小项目来说并不是什么大不了的事,但是立即采取这种习惯应该是个好习惯。 (我认为有一个免费的pdf格式的快速入门指南,作者Paul Martz,它可能对你有帮助。)
  • osgViewer::Viewer附带“默认”相机,您可以使用.getCamera()获取。对于您当前需要的内容,您必须将视图矩阵设置为(.setViewMatrixAsLookAt())。它需要三个矢量:眼睛,中心和向上,用于定位和定向相机。
  • 在OSG,我从未听过将相机保持在固定位置并改变世界的做法。您需要移动相机并将世界保持在固定位置以避免任何脑损伤。
  • 我不熟悉它(我没有亲自使用它),但我认为有一个名为osgGA::CameraManipulator的基类可以用于常见的相机操作。
  • 很高兴知道:osg::Cameraosg::Transform osg::Group,这意味着您可以将相机放入场景图中,只显示其下方的内容。嗯,这有点先进,但仍然。

以下是您的代码的副本,其中框已注释掉,模型已更改并添加了osg::ref_ptr。由于您手动定位相机,因此不再需要轨迹球操纵器。

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/PositionAttitudeTransform>
#include <osgGA/TrackballManipulator>
#include <osgViewer/ViewerEventHandlers>

using namespace osg;

int main()
{
    osgViewer::Viewer viewer;

    viewer.setUpViewInWindow(50,50,800,800);

    osg::ref_ptr<osg::Group> root (new osg::Group);

    osg::Node* terrain = osgDB::readNodeFile("C:\\DevTools\\OpenSceneGraph\\examples\\OpenSceneGraph-Data\\cessna.osg");
    if(terrain == nullptr) {
        return -1;
    }

    //Geode* gbox = new Geode();
    //gbox->addDrawable(new ShapeDrawable(new Box()));

    osg::ref_ptr<PositionAttitudeTransform> terrainT = new PositionAttitudeTransform();

    //PositionAttitudeTransform* boxT = new PositionAttitudeTransform();
    //boxT->setScale(Vec3d(50,50,50));
    //boxT->setPosition(Vec3d(1000,1000,0)); 

    root->addChild(terrainT);
    //root->addChild(boxT);
    terrainT->addChild(terrain);
    //boxT->addChild(gbox);

    viewer.setSceneData( root.get() ); 
    osg::ref_ptr<osgViewer::WindowSizeHandler> handler = new osgViewer::WindowSizeHandler();
    viewer.addEventHandler( handler );
//    viewer.setCameraManipulator(new osgGA::TrackballManipulator());
    Vec3d eye( 1000.0, 1000.0, 0.0 );
    Vec3d center( 0.0, 0.0, 0.0 );
    Vec3d up( 0.0, 0.0, 1.0 );

    viewer.getCamera()->setViewMatrixAsLookAt( eye, center, up );

    viewer.realize();
    while(!viewer.done()) {
        viewer.frame(); 
    }


    return 0;
}

玩得开心!