简介
使用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;
}