使用OpenSceneGraph (osg)实现一个星系漫游

发布于:2025-04-15 ⋅ 阅读:(18) ⋅ 点赞:(0)
简介

使用OpenSceneGraph (osg)实现了一个太阳系漫游的程序,具有以下特点:

1.通过按键控制飞行器前进后退、空间姿态;

2.星系渲染;

3.背景星空渲染;

效果

 

提供了一张超大的星空背景图 

代码示例
int main(int argc, char *argv[])
{
    // 创建场景根节点
    osg::ref_ptr<osg::Group> root = new osg::Group;
    root->addChild(createSun());
    root->addChild(createMercury());
    root->addChild(createVenus());
    root->addChild(createEarth());
    root->addChild(createMars());
    root->addChild(createJupiter());
    root->addChild(createSaturn());
    root->addChild(createUranus());
    root->addChild(createNeptune());

    root->addChild(createSkyBox());

    osg::ref_ptr<osg::MatrixTransform> airplaneTransform = new osg::MatrixTransform;
    osg::Vec3 craftPos(0, -40, 0);
    airplaneTransform->addChild(createAircraft()); // 或加载外部模型
    root->addChild(airplaneTransform);

    osgViewer::Viewer viewer;
    viewer.setSceneData(root.get());

    AircraftController* ac=new AircraftController(airplaneTransform.get());
    ac->setViewer(&viewer);
    ac->initCamera(craftPos);
    viewer.addEventHandler(ac);
    viewer.setUpViewInWindow(100, 100, 1200, 1000);

    // 2. 创建 HUD 相机
    osg::Camera* hudCamera = createHUDCamera(1200, 1000); // 假设窗口大小为 1280x720
    osg::ref_ptr<osg::Geode> hudGeode = new osg::Geode;

    // // 3. 添加状态文字到 HUD
    osgText::Text* statusText = createStatusText("", 1200, 20); // 右下角位置
    AircraftHudTextCallback* acHudCb=new AircraftHudTextCallback(airplaneTransform.get());
    statusText->setUpdateCallback(acHudCb);
    hudGeode->addDrawable(statusText);
    hudCamera->addChild(hudGeode);

    // 4. 将 HUD 相机添加到场景
    root->addChild(hudCamera);
    // viewer.setLightingMode( osg::View::SKY_LIGHT );
    while(!viewer.done())
	{
        viewer.frame();
    } 
    // return viewer.run();
}
osg::ref_ptr<osg::Node> createSun()
{
    osg::ref_ptr<osg::Sphere> sphere = new osg::Sphere(osg::Vec3(0, 0, 0), 1);
    osg::ref_ptr<osg::ShapeDrawable> sphereDrawable = new osg::ShapeDrawable(sphere);
    sphereDrawable->setColor(osg::Vec4(1.0, 0.6, 0.4, 1.0));
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(sphereDrawable);
    // 加载纹理
    // 设置渲染状态
    osg::ref_ptr<osg::StateSet> stateSet = geode->getOrCreateStateSet();
    stateSet->setTextureAttributeAndModes(0, create_texture("sun.jpg"));
    // 创建 MatrixTransform 节点
    osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;

    // 将球体添加到变换节点
    transform->addChild(geode);

    // 创建回调并附加到变换节点
    transform->setUpdateCallback(new SpinCallback(0.001*velocityRate,osg::Vec3(0, 0, 1)));
    return transform;
}
osg::ref_ptr<osg::Node> createJupiter()
{
    std::string name="Jupiter";
    osg::ref_ptr<osg::Sphere> sphere =new osg::Sphere(osg::Vec3(0, 0, 0), get_param(name,"size"));
    osg::ref_ptr<osg::ShapeDrawable> sphereDrawable = new osg::ShapeDrawable(sphere);
    sphereDrawable->setColor(osg::Vec4(0.95, 0.86, 0.54, 1.0));
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(sphereDrawable);
    // 加载纹理
     // 设置渲染状态
    osg::ref_ptr<osg::StateSet> stateSet = geode->getOrCreateStateSet();
    stateSet->setTextureAttributeAndModes(0, create_texture("jupiter.jpg"));


    //
    double inner_radius=3/1.8*get_param(name,"size");
    double outer_radius=4.2/1.8*get_param(name,"size");
    osg::ref_ptr<osg::Geometry> ringGeometry=createRingGeometry(inner_radius,outer_radius,64);
    // ringGeometry->setColor(osg::Vec4(0.95, 0.86, 0.54, 0.9));
    osg::ref_ptr<osg::Geode> geode2=new osg::Geode;
    geode2->addDrawable(ringGeometry);

    osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
    transform->addChild(geode);
    transform->addChild(geode2);

    OrbitAndSpinCallback* cb=new OrbitAndSpinCallback();
    cb->setInit(get_param(name,"leanAngle"),osg::Vec3(0,1,0));
    cb->setOrbit(get_param(name,"orbitAngleVelocity"),get_param(name,"orbitRadius"),osg::Vec3(0, 0, 1.0));
    cb->setSpin(get_param(name,"spinAngleVelocity"),osg::Vec3(tan(get_param(name,"leanAngle")), 0, 1));

    transform->setUpdateCallback(cb);
    osg::ref_ptr<osg::Group> group = new osg::Group;
    group->addChild(createMoon("Lo",cb));
    group->addChild(createMoon("Europa",cb));
    group->addChild(createMoon("Callisto",cb));
    group->addChild(createMoon("Ganymede",cb));
    group->addChild(transform);
    print_plannet_info(name);
    return group;    
}
资源链接

http://antown.net/item_introduction/solarsystem


网站公告

今日签到

点亮在社区的每一天
去签到