整体代码的主函数部分如下:
/*********************************************************
main.cpp
*********************************************************/
#include "Include.h"
#include "MyCamera.h"
#include "MyLabelMenu.h"
#include "AutoCars.h"
#include "MyEventCallback.h"
#include "MyRecordCameraPathToFile.h"
const char *titleString = "操作说明";
const char *textString =
{
"a: 向左看 i: 汽车加速\n"
"d: 向右看 j: 汽车左转\n"
"w: 向下看 k: 汽车减速\n"
"s: 向上看 l: 汽车右转\n"
"空格:视角变换 o: 汽车停止\n"
"F1: 显示/隐藏帮助 F3: 全屏/窗口切换\n"
"F2: 打开/关闭车灯 F4:初始化汽车位置\n"
"空格: 第一/第三人称视角"
};
using namespace std;
using namespace osgEarth;
void installMemoryLeakDetector()
{
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
//_crtBreakAlloc = 10923;
#endif
}
//创建覆盖整个场景的光源信息
osg::ref_ptr<osg::Node> createLights()
{
osg::ref_ptr<osg::Light> myLight1 = new osg::Light;
myLight1->setLightNum(0);
myLight1->setPosition(osg::Vec4(0.0f, 0.0f, 4800.0f, 1.0f));
myLight1->setAmbient(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
myLight1->setDiffuse(osg::Vec4(0.25f, 0.25f, 0.25f, 0.25f));
myLight1->setSpecular(osg::Vec4(0.0f, 0.0f, 0.0f, 0.25f));
myLight1->setConstantAttenuation(1.0f); //设置恒衰减指数
myLight1->setLinearAttenuation(0.0f); //设置线性衰减指数
myLight1->setQuadraticAttenuation(0.0f); //设置二次方衰减指数
myLight1->setDirection(osg::Vec3(0.0, 0.0, -2000.0f));
osg::ref_ptr<osg::LightSource> lightS1 = new osg::LightSource;
lightS1->setLight(myLight1);
lightS1->setName(gSceneLight);
lightS1->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);
osg::ref_ptr<osg::Group> group = new osg::Group;
group->addChild(lightS1);
return group.get();
}
//创建车灯
osg::ref_ptr<osg::Node> createSpotLamp(osg::ref_ptr<osg::Node> car)
{
osg::BoundingSphere bs = car->getBound();
osg::BoundingBox bb;
bb.expandBy(bs);
float modelSize = bb.radius()*10;
osg::Vec4 pos(bb.center().x(), bb.center().y(), bb.center().z(), 1.0f);
osg::Vec3 direction(bb.center().x() - modelSize, bb.center().y(), -modelSize / 4.0f);
osg::ref_ptr<osg::Light> light1 = new osg::Light;
light1->setLightNum(1);
light1->setDiffuse(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
light1->setAmbient(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
light1->setSpecular(osg::Vec4(0.0f, 0.0f, 0.0f, 0.f));
light1->setPosition(pos);
light1->setDirection(direction);
light1->setSpotCutoff(20.0f);
light1->setSpotExponent(10.0f);
osg::ref_ptr<osg::LightSource> lightSource1 = new osg::LightSource;
lightSource1->setLight(light1);
lightSource1->setLocalStateSetModes(osg::StateAttribute::ON);
lightSource1->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);
osg::ref_ptr<osg::PositionAttitudeTransform> pat1 = new osg::PositionAttitudeTransform;
pat1->addChild(lightSource1.get());
pat1->setName(gLeftSpotLampName);
osg::ref_ptr<osg::Group> group = new osg::Group;
group->addChild(pat1.get());
开启光照
//osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
//stateset = group->getOrCreateStateSet();
//stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON);
//stateset->setMode(GL_LIGHT0, osg::StateAttribute::ON);//允许GL_LIGHT0光照
//stateset->setMode(GL_LIGHT1, osg::StateAttribute::ON);//允许GL_LIGHT1光照
group->getOrCreateStateSet()->setMode(GL_LIGHT1, osg::StateAttribute::ON);
return group.get();
}
/*
驾驶员控制的车辆
功能:对模型model按照位置和姿态(写死的)及缩放变换后返回其node
参数:1、位置坐标。2、缩放比例
*/
osg::ref_ptr<osg::Node> createPlayCar(osg::Vec3 vPos, osg::Vec3 vScale, osg::Node* model)
{
osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;//位姿转换
pat->addChild(model);//将要加载到的节点
pat->setPosition(vPos);//位置坐标
osg::Quat quat(osg::DegreesToRadians(-90.0), osg::Z_AXIS);//位置旋转坐标
pat->setAttitude(quat);
pat->setScale(vScale);//缩放比例
pat->setName("MyPlayCar");//设置名称
return pat.get();//返回位姿转换信息(应该是矩阵)的模型(由于返回类型是node类型)
}
//创建雾效
osg::ref_ptr<osg::Fog> createFog()
{
osg::ref_ptr<osg::Fog> fog = new osg::Fog();
fog->setColor(osg::Vec4(0.5f, 0.5f, 0.5f, 0.0f));
fog->setDensity(0.05f);
fog->setMode(osg::Fog::LINEAR);
fog->setStart(0.0f);
fog->setEnd(400.0f);
return fog.get();
}
//创建驾驶场景
osg::ref_ptr<osg::Node> createScene(osg::Node* model)
{
osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;
pat->addChild(model);
pat->setScale(osg::Vec3(100.0f, 100.0f, 100.0f));
osg::BoundingSphere bs = pat->getBound();
pat->setPosition(osg::Vec3(0 - bs.center().x(), 0 - bs.center().y(), 0 - bs.center().z()));
pat->setName("MyScene");
return pat.get();
}
//创建驾驶场景
osg::ref_ptr<osg::Node> createEarthScene(osg::Node* model)
{
osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;
pat->addChild(model);
pat->setScale(osg::Vec3(1.0f, 1.0f, 1.0f));
osg::BoundingSphere bs = pat->getBound();
pat->setPosition(osg::Vec3(0 - bs.center().x(), 0 - bs.center().y(), 0 - bs.center().z()));
pat->setName("MyScene");
return pat.get();
}
//创建雨、雪效果
osg::ref_ptr<osgParticle::PrecipitationEffect> createPrecipitationEffect()
{
osg::ref_ptr<osgParticle::PrecipitationEffect> precipitationEffect = new osgParticle::PrecipitationEffect;
precipitationEffect->rain(0.0); //雨
precipitationEffect->snow(0.0); //雪
precipitationEffect->setCellSize(osg::Vec3(2.0f, 2.0f, 2.0f));
precipitationEffect->setParticleSize(0.8f);
precipitationEffect->setParticleColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
precipitationEffect->setWind(osg::Vec3(2, 0, 0));
precipitationEffect->setUseFarLineSegments(true);
precipitationEffect->setName(gPrecipitationEffectName);
return precipitationEffect.get();
}
//创建一个图元碎片(给一个四边形贴上纹理)
osg::ref_ptr<osg::Geometry> createSegment(float x, float y, float z, osg::ref_ptr<osg::Image> image, \
bool cullFlag, float alpha)
{
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
//定义四个点
osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
v->push_back(osg::Vec3(0.0f, y, z)); //逆时针
v->push_back(osg::Vec3(0.0f, 0.0f, z));
v->push_back(osg::Vec3(x, 0.0f, z));
v->push_back(osg::Vec3(x, y, z));
geom->setVertexArray(v.get());
//定义法线
osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;
osg::Vec3f upVec(0.0f, 0.0f, 1.0f);
n->push_back(upVec);
geom->setNormalArray(n.get());
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
//设置纹理坐标
osg::ref_ptr<osg::Vec2Array> geomTexcoords = new osg::Vec2Array(4);
(*geomTexcoords)[0].set(0.0f, 1.0f);
(*geomTexcoords)[1].set(0.0f, 0.0f);
(*geomTexcoords)[2].set(1.0f, 0.0f);
(*geomTexcoords)[3].set(1.0f, 1.0f);
geom->setTexCoordArray(0, geomTexcoords.get());
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(0.5f, 0.5f, 0.5f, alpha));
geom->setColorArray(colors);
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
//设置顶点关联方式
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
osg::StateSet* geomState = geom->getOrCreateStateSet();
geomState->setAttributeAndModes(new osg::BlendFunc, osg::StateAttribute::ON);
if (cullFlag) //背面剔除
{
osg::ref_ptr<osg::CullFace> cullface = new osg::CullFace(osg::CullFace::BACK);
geomState->setAttribute(cullface.get());
geomState->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
}
if (image) //如果要添加纹理
{
osg::ref_ptr<osg::Texture2D> tex = new osg::Texture2D;
tex->setImage(image.get());
geomState->setTextureAttributeAndModes(0, tex.get(), osg::StateAttribute::ON);
}
return geom.get();
}
//创建速度显示节点
osg::ref_ptr<osg::Node> createSpeedNode()
{
osg::ref_ptr<osgText::Text> text = new osgText::Text();
text->setFont("fonts/simhei.ttf");
text->setCharacterSize(4.0f);
text->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
text->setAlignment(osgText::Text::CENTER_CENTER);
text->setAxisAlignment(osgText::Text::XY_PLANE);
text->setText("0.0 Km/h");
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
geode->addDrawable(text.get()); //绘制速度文本
geode->setName(gSpeedTextName); //给该速度节点设置名字
geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); //关闭光照
osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;
pat->addChild(geode.get());
pat->setPosition(osg::Vec3(-1.0f, 8.724f, 15.60f)); //设置文本的初始化位置(即相对于汽车的位置)
pat->setScale(osg::Vec3(0.07f, 0.07f, 0.07f));
pat->setAttitude(osg::Quat(osg::DegreesToRadians(90.0f), osg::X_AXIS)); //旋转
osg::ref_ptr<osg::PositionAttitudeTransform> pat1 = new osg::PositionAttitudeTransform;
pat1->addChild(pat.get()); //在程序的运行过程中,每帧都会更新该节点的位置信息
pat1->setName(gSpeedNodeName); //速度节点的最终位置等于他所有父节点的位置矩阵相乘
return pat1.get();
}
//创建方向指示器
osg::ref_ptr<osg::Node> createCompassNode()
{
//
osg::ref_ptr<osg::Image> compass = osgDB::readImageFile("compass.bmp");
osg::ref_ptr<osg::Geometry> compassGeom = createSegment(1.0f, 1.0f, 0.0f, compass, true, 1.0f);
osg::ref_ptr<osg::Geode> compassGeode = new osg::Geode;
compassGeode->addDrawable(compassGeom.get());
osg::ref_ptr<osg::PositionAttitudeTransform> compassPat = new osg::PositionAttitudeTransform;
compassPat->addChild(compassGeode.get());
compassPat->setPivotPoint(osg::Vec3(0.5f, 0.5f, 0.0f));
compassPat->setPosition(osg::Vec3(0.5f, 0.5f, 0.0f));
compassPat->setName(gCompassName); //在程序的运行过程中,会根据汽车的旋转状态更新此方向盘的旋转状态
//指针
osg::ref_ptr<osg::Image> point = osgDB::readImageFile("pointer.bmp");
osg::ref_ptr<osg::Geometry> pointGeom = createSegment(0.8f, 0.1f, 0.001f, point, true, 1.0);
osg::ref_ptr<osg::Geode> pointGeode = new osg::Geode;
pointGeode->addDrawable(pointGeom.get());
osg::ref_ptr<osg::PositionAttitudeTransform> pointPat = new osg::PositionAttitudeTransform;
pointPat->addChild(pointGeode.get());
pointPat->setAttitude(osg::Quat(osg::DegreesToRadians(-90.0f), osg::Z_AXIS));
pointPat->setScale(osg::Vec3(0.4f, 0.5f, 0.5f));
pointPat->setPosition(osg::Vec3(0.5f, 0.83f, 0.0f));
osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;
pat->addChild(compassPat.get());
pat->addChild(pointPat.get());
pat->setPosition(osg::Vec3(-1.8, 6.455, 15.2));
pat->setAttitude(osg::Quat(osg::DegreesToRadians(90.0), osg::X_AXIS));
osg::ref_ptr<osg::PositionAttitudeTransform> pat1 = new osg::PositionAttitudeTransform;
pat1->setName(gCompassNodeName); //每帧都会根据汽车当前的位置更新pat1的位置
pat1->addChild(pat.get());
pat1->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
pat1->getOrCreateStateSet()->setMode(GL_LIGHT0, osg::StateAttribute::OFF);
pat1->getOrCreateStateSet()->setMode(GL_LIGHT1, osg::StateAttribute::OFF);
return pat1.get();
}
//创建自动行驶的汽车
osg::ref_ptr<osg::Node> createAutoCar(float rotatef, osg::Vec3 start, osg::Vec3 end, osg::Vec3 speed,
osg::Vec3 scale, char axis, osg::Node *model)
{
osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;
pat->addChild(model);
pat->setScale(scale);
pat->setAttitude(osg::Quat(osg::DegreesToRadians(rotatef), osg::Z_AXIS));
pat->setPosition(start);
pat->addUpdateCallback(new CAutoCar(start, end, speed, axis, rotatef));
return pat.get();
}
//给屏幕添加多辆自动驾驶的汽车
osg::ref_ptr<osg::Node> createAutoCars()
{
osg::ref_ptr<osg::Group> group = new osg::Group;
osg::ref_ptr<osg::Node> publicCar = osgDB::readNodeFile("publicCar.ive"); //公交车
osg::ref_ptr<osg::Node> playCar = osgDB::readNodeFile("playerCar.ive"); //小轿车
group->addChild(createAutoCar(180.0f, osg::Vec3(-2000.0f, 20.0f, 0.0f), osg::Vec3(2000.0f, 20.0f, 0.0f),
osg::Vec3(3.0f, 0.0f, 0.0f), osg::Vec3(4.5f, 4.5f, 4.5f), 'x', publicCar.get()).get());
group->addChild(createAutoCar(90.0f, osg::Vec3(-50.0f, -450.0f, 0.0f), osg::Vec3(-50.0f, 2000.0f, 0.0f),
osg::Vec3(0.0f, 4.0f, 0.0f), osg::Vec3(4.5f, 4.5f, 4.5f), 'y', publicCar.get()).get());
//可以在此添加更多的汽车
return group.get();
}
//给场景添加雾效
void addStateSet(osg::ref_ptr<osg::Group> root)
{
osg::StateSet *stateset = root->getOrCreateStateSet();
stateset->setAttributeAndModes(createFog(), osg::StateAttribute::OFF);
stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON);
stateset->setMode(GL_LIGHT0, osg::StateAttribute::ON);
stateset->setMode(GL_LIGHT1, osg::StateAttribute::OFF);
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
}
void setupProperties(osgText::Text& textObject, osgText::Font *font, float size, const osg::Vec3 &pos)
{
textObject.setFont(font); //设置文本的各种信息
textObject.setCharacterSize(size);
textObject.setPosition(pos);
textObject.setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0));
textObject.setAlignment(osgText::Text::LEFT_TOP); //左上角对齐
textObject.setAxisAlignment(osgText::Text::XZ_PLANE);//在XZ平面上
}
void createContent(osgText::Text &textObject, const char *string)
{
int requiredSize = mbstowcs(NULL, string, 0); //文本字体格式转换,使其支持中文
wchar_t *wtext = new wchar_t[requiredSize + 1];
mbstowcs(wtext, string, requiredSize + 1);
textObject.setText(wtext);
delete wtext;
wtext = NULL;
}
//帮助窗口
osg::ref_ptr<osg::Node> createHelpNode()
{
setlocale(LC_ALL, ".936");
osgText::Font* fontHei = osgText::readFontFile("Fonts/simhei.ttf");
osg::ref_ptr<osgText::Text> title = new osgText::Text;
setupProperties(*title, fontHei, 1.5f, osg::Vec3(0.0f, 0.0f, 0.0f));
createContent(*title, titleString);
osg::ref_ptr<osgText::Text> text = new osgText::Text;
setupProperties(*text, fontHei, 1.0f, osg::Vec3(0.0f, 0.0f, 0.0f));
createContent(*text, textString);
//
osg::ref_ptr<osg::Geode> geode1 = new osg::Geode;
geode1->addDrawable(createSegment(30.0f, 14.0f, 0.0f, NULL, true, 0.4f));
osg::ref_ptr<osg::PositionAttitudeTransform> pat1 = new osg::PositionAttitudeTransform;
pat1->addChild(geode1.get());
pat1->setAttitude(osg::Quat(osg::DegreesToRadians(90.0f), osg::X_AXIS));
pat1->setPosition(osg::Vec3(0.0f, 0.05f, 0.0f));
//
osg::ref_ptr<osg::Geode> geode2 = new osg::Geode;
geode2->addDrawable(title.get());
osg::ref_ptr<osg::PositionAttitudeTransform> pat2 = new osg::PositionAttitudeTransform;
pat2->addChild(geode2.get());
pat2->setPosition(osg::Vec3(12.5f, 0.0f, 12.5f));
//
osg::ref_ptr<osg::Geode> geode3 = new osg::Geode;
geode3->addDrawable(text.get());
osg::ref_ptr<osg::PositionAttitudeTransform> pat3 = new osg::PositionAttitudeTransform;
pat3->addChild(geode3.get());
pat3->setPosition(osg::Vec3(6.0f, 0.0f, 10.0f));
//
osg::ref_ptr<osg::PositionAttitudeTransform> pat4 = new osg::PositionAttitudeTransform;
pat4->addChild(pat1.get());
pat4->addChild(pat2.get());
pat4->addChild(pat3.get());
pat4->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
pat4->getOrCreateStateSet()->setMode(GL_LIGHT0, osg::StateAttribute::OFF);
pat4->getOrCreateStateSet()->setMode(GL_LIGHT1, osg::StateAttribute::OFF);
osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;
pat->addChild(pat4.get());
pat->setName(gHelpNodeName);
return pat.get();
}
//仿照<osgEarthUtil/ExampleResources>中,通过读取命令行的形式读取参数(地球和_sky),实实现获得带有sky的地球
osg::Group* load(osg::ArgumentParser& args, osgViewer::Viewer* view)
{
Config c;
c.add("elevation_smoothing", false);
TerrainOptions to(c);
MapNodeOptions defMNO;
defMNO.setTerrainOptions(to);
osg::Node* node = osgDB::readNodeFile("G:/YCThirdParty/EarthData/demo.earth");
osg::ref_ptr<MapNode> mapNode = MapNode::get(node);
// a root node to hold everything:
osg::Group* root = new osg::Group();
root->addChild(node);
if (view)
{
//1
if (!root)
root = mapNode.get();
// options to use for the load
osg::ref_ptr<osgDB::Options> dbOptions = osgEarth::Registry::instance()->cloneOrCreateOptions();
ControlCanvas* canvas = ControlCanvas::getOrCreate(view);
Container* mainContainer;
{
mainContainer = new VBox();
mainContainer->setAbsorbEvents(true);
mainContainer->setBackColor(Color(Color::Black, 0.2));
mainContainer->setHorizAlign(Control::ALIGN_RIGHT);
mainContainer->setVertAlign(Control::ALIGN_BOTTOM);
}
canvas->addControl(mainContainer);
const Config& externals = mapNode->externalConfig();
mapNode->addExtension(Extension::create("sky_simple", ConfigOptions()));//增加天空、大气效果。
Hook up the extensions!增加拖拽条功能。
for (std::vector<osg::ref_ptr<Extension> >::const_iterator eiter = mapNode->getExtensions().begin(); eiter != mapNode->getExtensions().end(); ++eiter)
{
Extension* e = eiter->get();
// Check for a View interface:
ExtensionInterface<osg::View>* viewIF = ExtensionInterface<osg::View>::get(e);
if (viewIF)
viewIF->connect(view);
}
root->addChild(canvas);
//1
}
if (view)
{
//configureView( view );
view->addEventHandler(new osgViewer::StatsHandler());
view->addEventHandler(new osgViewer::WindowSizeHandler());
view->addEventHandler(new osgViewer::ThreadingHandler());
view->addEventHandler(new osgViewer::LODScaleHandler());
view->addEventHandler(new osgGA::StateSetManipulator(view->getCamera()->getOrCreateStateSet()));
//view->addEventHandler(new osgViewer::RecordCameraPathHandler());
view->addEventHandler(new osgViewer::ScreenCaptureHandler());
}
return root;
}
// 世界坐标转经纬度
osg::Vec3d WorldToLonLatAlt(const osg::Vec3d world)
{
osg::EllipsoidModel* em = new osg::EllipsoidModel();
osg::Vec3d lonLatAlt;
em->convertXYZToLatLongHeight(world.x(), world.y(), world.z(),
lonLatAlt.y(), lonLatAlt.x(), lonLatAlt.z());
lonLatAlt.x() = osg::RadiansToDegrees(lonLatAlt.x());
lonLatAlt.y() = osg::RadiansToDegrees(lonLatAlt.y());
return lonLatAlt;
}
//经纬度转世界坐标系
osg::Vec3d LonLatAltToWorld(const osg::Vec3d lonLatAlt)
{
osg::Vec3d world;
osg::EllipsoidModel* em = new osg::EllipsoidModel();
//Lat纬度Long经度
em->convertLatLongHeightToXYZ(osg::DegreesToRadians(lonLatAlt.y()),
osg::DegreesToRadians(lonLatAlt.x()), lonLatAlt.z(), world.x(), world.y(), world.z());
return world;
}
//int main_driver(int argc, char **argv)
//模拟自动驾驶,通过参数切换是自动驾驶还是手动驾驶,实际中,手动驾驶有问题。地球的位置不对。
int main_driver()
{
installMemoryLeakDetector();
setlocale(LC_ALL, "chs");
cout << "请稍等,正在加载程序运行资源...";
osgViewer::Viewer viewer;
osgWidget::WindowManager* wm = new osgWidget::WindowManager(&viewer, WINDOW_WIDTH, WINDOW_HEIGHT, MASK_3D);
osgWidget::Window *menu = new osgWidget::Box("menu", osgWidget::Box::HORIZONTAL);
menu->addWidget(new CMyLabelMenu("菜单")); //添加菜单按钮
menu->getBackground()->setColor(1.0f, 1.0f, 1.0f, 1.0f);
menu->setPosition(15.0f, 15.0f, 0.0f);
wm->addChild(menu);
改为地球的model
//模拟命令行内容
int argc = 2;
char* argv[] = { "11" ,"G:/YCThirdParty/EarthData/demo.earth","--sky" };
osg::ArgumentParser args1(&argc, argv);//通过命令行的方式加载带有sky的earth(源于oe的源代码)
ref_ptr <Node> MyScene = load(args1, &viewer);//加载地球
if (!MyScene)
{
osg::notify(osg::NOTICE) << "No MyScene " << std::endl;
return 1;
}
改为地球的model
osg::ref_ptr<osg::Group> root = new osg::Group();
//root->addChild(createEarthScene(MyScene).get()); //整个地球节点(包含sky),此处在加载时,做了加载中转转换(未完全弄懂)
root->addChild( (MyScene) ); //整个地球节点(包含sky)
osg::ref_ptr<osg::Node> car = osgDB::readNodeFile("MyCar.ive");
if (!car)
{
osg::notify(osg::NOTICE) << "No Car " << std::endl;
return 1;
}
/设置相机的初始地球位置↓
root->addChild(createPrecipitationEffect().get()); //添加粒子效果,如“雪天、雾天”(初始化的一些操作,一下几个操作类似)
addStateSet(root);
root->addChild(createHelpNode().get()); // 添加帮助窗口
root->addChild(createLights().get()); // 添加全局光照
root->addChild(createSpotLamp(car).get()); // 添加车灯
root->addChild(createSpeedNode().get()); // 添加速度计
root->addChild(createCompassNode().get()); // 添加方向显示器
//root->setEventCallback(new CMyEventCallback(false)); //设置事件监听回调函数true/false(是否为自动驾驶)
root->setEventCallback(new CMyEventCallback(false)); // 测试不适应operator()
viewer.setRunMaxFrameRate(125);//设置帧率
osg::Vec3d cameraPosition = LonLatAltToWorld(Vec3d(116, 40, 0));//将经纬度转换成世界坐标系centerLat = 46.0;centerLon = 46.0;
osg::Vec3d CARPosition = LonLatAltToWorld(Vec3d(116, 40, 0 ));
root->addChild(createPlayCar(CARPosition, osg::Vec3(0.1, 0.1, 0.1), car.get())); //汽车加载,并设置好加载的位置、尺寸缩放、姿态等信息
osg::ref_ptr<CMyCamera> camera = new CMyCamera();
camera->setPosition(cameraPosition); //设置摄像机的初始位置
//camera->setHomeViewpoint(Viewpoint("Home",
// -71.0763, 42.34425, 0, // longitude, latitude, altitude
// 24.261, -21.6, 3450.0), // heading, pitch, range
// 5.0); // duration
viewer.setCameraManipulator(camera);//相机操作器(其继承与类CameraManipulator)
viewer.addEventHandler(new CMyViewerHandler); //重写原始的操作器,内容什么都没有写,目的是用以屏蔽原来的键盘鼠标操作
/设置相机的初始地球位置↑
return osgWidget::createExample(viewer, wm, root);
}
/*
#if 0//是否添加处理earth以外的其他物体
#endif
///由经纬度获得高程
osgEarth::ElevationQuery *query;
ref_ptr<MapNode> mapNode1 = osgEarth::MapNode::findMapNode(MyScene);
if (!mapNode1){
OE_NOTICE << "Could not find MapNode " << std::endl;
return -1;
}
query = new osgEarth::ElevationQuery(mapNode1->getMap());
double query_resolution = 0.00000001;
double out_hamsl = 0.0;
double out_resolution = 0.0;
query->getElevation(GeoPoint(mapNode1->getMapSRS(), 116, 40, 0.0, osgEarth::AltitudeMode::ALTMODE_ABSOLUTE),out_hamsl,query_resolution,&out_resolution);
///由经纬度获得高程
*/
核心代码(1)加载带有天空(sky)的地球
//仿照<osgEarthUtil/ExampleResources>中,通过读取命令行的形式读取参数(地球和_sky),实实现获得带有sky的地球
osg::Group* load(osg::ArgumentParser& args, osgViewer::Viewer* view)
{
Config c;
c.add("elevation_smoothing", false);
TerrainOptions to(c);
MapNodeOptions defMNO;
defMNO.setTerrainOptions(to);
osg::Node* node = osgDB::readNodeFile("G:/YCThirdParty/EarthData/demo.earth");
osg::ref_ptr<MapNode> mapNode = MapNode::get(node);
// a root node to hold everything:
osg::Group* root = new osg::Group();
root->addChild(node);
if (view)
{
//1
if (!root)
root = mapNode.get();
// options to use for the load
osg::ref_ptr<osgDB::Options> dbOptions = osgEarth::Registry::instance()->cloneOrCreateOptions();
ControlCanvas* canvas = ControlCanvas::getOrCreate(view);
Container* mainContainer;
{
mainContainer = new VBox();
mainContainer->setAbsorbEvents(true);
mainContainer->setBackColor(Color(Color::Black, 0.2));
mainContainer->setHorizAlign(Control::ALIGN_RIGHT);
mainContainer->setVertAlign(Control::ALIGN_BOTTOM);
}
canvas->addControl(mainContainer);
const Config& externals = mapNode->externalConfig();
mapNode->addExtension(Extension::create("sky_simple", ConfigOptions()));//增加天空、大气效果。
Hook up the extensions!增加拖拽条功能。
for (std::vector<osg::ref_ptr<Extension> >::const_iterator eiter = mapNode->getExtensions().begin(); eiter != mapNode->getExtensions().end(); ++eiter)
{
Extension* e = eiter->get();
// Check for a View interface:
ExtensionInterface<osg::View>* viewIF = ExtensionInterface<osg::View>::get(e);
if (viewIF)
viewIF->connect(view);
}
root->addChild(canvas);
//1
}
if (view)
{
//configureView( view );
view->addEventHandler(new osgViewer::StatsHandler());
view->addEventHandler(new osgViewer::WindowSizeHandler());
view->addEventHandler(new osgViewer::ThreadingHandler());
view->addEventHandler(new osgViewer::LODScaleHandler());
view->addEventHandler(new osgGA::StateSetManipulator(view->getCamera()->getOrCreateStateSet()));
//view->addEventHandler(new osgViewer::RecordCameraPathHandler());
view->addEventHandler(new osgViewer::ScreenCaptureHandler());
}
return root;
}
核心代码(2) MyEventCallback类,实现键盘的交互,并在交互中,实时刷新,
1)MyEventCallback.cpp的内容
#include "MyEventCallback.h"
extern bool gSnow; //定义在MyLabelMenu.cpp文件
extern bool gFog;
extern bool gHelp;
extern bool gRain;
extern bool gNight;
extern bool gFullScreen;
extern bool gMousePush;
CMyEventCallback::CMyEventCallback(bool auto_Drive)//通过在新建类的时候,传入不同的值,实现自动操作和手动操作(专业的应该是:使用外部按键来切换)
{
m_speed = 0.0f;//速度的初始值
m_rotatef = 0.0f;
m_fogFlag = false;
m_theThreeView = false;
m_DisplayHelp = false;
m_flag_Auto_Drive = !auto_Drive;
}
CMyEventCallback::~CMyEventCallback()
{
}
//初始化类中成员变量
void CMyEventCallback::init(osg::Node* node, osg::NodeVisitor* nv)
{
//得到整个场景的根节点
m_rootNode = dynamic_cast<osg::Group*>(node);
//得到整个场景的摄像机节点
osg::ref_ptr<osgGA::EventVisitor> ev = dynamic_cast<osgGA::EventVisitor*>(nv);
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(ev->getActionAdapter());
m_camera = dynamic_cast<CMyCamera*>(viewer->getCameraManipulator());
//得到窗口信息
vector<osgViewer::GraphicsWindow*> vgw;
viewer->getWindows(vgw);
m_gw = vgw[0];
//得到屏幕分辨率
osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface();
wsi->getScreenResolution(*(m_gw->getTraits()), m_screenWidth, m_screenHeight);
//初始化窗口模式时 窗口的位置和宽、高
m_screenWindowWidth = m_screenWidth*0.75;
m_screenWindowHeight = m_screenHeight*0.75;
m_screenX = (m_screenWidth - m_screenWindowWidth) / 2;
m_screenY = (m_screenHeight - m_screenWindowHeight) / 2;
//设置屏幕窗口大小
m_gw->setWindowRectangle(m_screenX, m_screenY, m_screenWindowWidth, m_screenWindowHeight);
//节点访问器
CMyNodeVisitor nodeVisitor;
//查找并获取汽车节点
nodeVisitor.setNameToFind("MyPlayCar");
m_rootNode->accept(nodeVisitor);
m_playCar = dynamic_cast<osg::PositionAttitudeTransform*>(nodeVisitor.getFindNode());
//查找并获取雨、雪节点
nodeVisitor.setNameToFind(gPrecipitationEffectName);
m_rootNode->accept(nodeVisitor);
m_precipitationEffect = dynamic_cast<osgParticle::PrecipitationEffect*>(nodeVisitor.getFindNode());
//查找并获取全局光源节点
nodeVisitor.setNameToFind(gSceneLight);
m_rootNode->accept(nodeVisitor);
m_sceneLight = dynamic_cast<osg::LightSource*>(nodeVisitor.getFindNode())->getLight();
//查找并获取汽车车灯
nodeVisitor.setNameToFind(gLeftSpotLampName);
m_rootNode->accept(nodeVisitor);
m_SpotLamp = dynamic_cast<osg::PositionAttitudeTransform*>(nodeVisitor.getFindNode());
//查找并获取方向显示器节点
nodeVisitor.setNameToFind(gCompassName);
m_rootNode->accept(nodeVisitor);
m_compass = dynamic_cast<osg::PositionAttitudeTransform*>(nodeVisitor.getFindNode());
//查找并获取方向图 节点
nodeVisitor.setNameToFind(gCompassNodeName);
m_rootNode->accept(nodeVisitor);
m_compassNode = dynamic_cast<osg::PositionAttitudeTransform*>(nodeVisitor.getFindNode());
//查找并获取驾驶速度文本节点
nodeVisitor.setNameToFind(gSpeedTextName);
m_rootNode->accept(nodeVisitor);
m_speedText = dynamic_cast<osgText::Text*>(dynamic_cast<osg::Geode*>(nodeVisitor.getFindNode())->getDrawable(0));
//查找并获取显示驾驶速度的位置节点
nodeVisitor.setNameToFind(gSpeedNodeName);
m_rootNode->accept(nodeVisitor);
m_speedNode = dynamic_cast<osg::PositionAttitudeTransform*>(nodeVisitor.getFindNode());
//查找并获取驾驶地图节点
nodeVisitor.setNameToFind("MyScene");
m_rootNode->accept(nodeVisitor);
m_map = dynamic_cast<osg::PositionAttitudeTransform*>(nodeVisitor.getFindNode());
//查找并获取显示帮助信息的节点
nodeVisitor.setNameToFind(gHelpNodeName);
m_rootNode->accept(nodeVisitor);
m_helpNode = dynamic_cast<osg::PositionAttitudeTransform*>(nodeVisitor.getFindNode());
//得到雾效状态
m_fog = dynamic_cast<osg::Fog*>(m_rootNode->getOrCreateStateSet()->getAttribute(osg::StateAttribute::FOG));
}
/
void CMyEventCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
static bool isInit = false;
if (!isInit) //在程序最开始运行的时候初始化类中成员变量(虽然每帧都会判断是否初始化,但是一旦初始化过,但并不执行)
{
init(node, nv);
isInit = true;
}
if (nv->getVisitorType() == osg::NodeVisitor::EVENT_VISITOR)//判断访问器类型
{
osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(nv);
if (!ev)
{
return;
}
else
{
osgGA::GUIActionAdapter* aa = ev->getActionAdapter(); //得到执行动作
osgGA::EventQueue::Events& events = ev->getEvents();
osgGA::EventQueue::Events::iterator itr;
for (itr = events.begin();itr != events.end();++itr)
{
osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
if (!event)
{
return;
}
else
{
if (m_flag_Auto_Drive)//手动驾驶模式
{
handle(*(event), *aa);
}
else//自动驾驶模式
{
m_speed += 0.2f;//让速度动态变起来
//保证其他东西也一起动起来
osg::Quat quat = osg::Quat(m_rotatef - osg::PI_2, osg::Z_AXIS);
m_playCar->setAttitude(quat);
m_SpotLamp->setAttitude(quat);
m_speedNode->setAttitude(osg::Quat(m_rotatef, osg::Z_AXIS));
m_compass->setAttitude(osg::Quat(m_rotatef, osg::Z_AXIS));
m_compassNode->setAttitude(osg::Quat(m_rotatef, osg::Z_AXIS));
m_camera->setRotatefZ(m_rotatef);
//设置汽车风向与行驶方向相等
m_precipitationEffect->setWind(osg::Vec3d(-m_speed*sin(m_rotatef), m_speed*cos(m_rotatef), 0.0));
//如果汽车的速度发生了变化,更新速度显示器的内容
float speed = ((int)(m_speed * 3600 * 30 / 1000)) / 20;
char text[12];
sprintf_s(text, "%.1f", speed);
string label(text);
label += " Km/h";
m_speedText->setText(label);
//设置粒子风向与汽车行驶方向相等
m_precipitationEffect->setWind(osg::Vec3d(-m_speed*sin(m_rotatef), m_speed*cos(m_rotatef), 0.0));
}
}
}
}
}
updateScene(); //每帧都需要更新场景数据
}
//处理每一个事件
bool CMyEventCallback::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
switch (ea.getEventType())
{
case osgGA::GUIEventAdapter::KEYDOWN:
{
m_key = ea.getKey();//判断按键值(实际中是不断判断---即在operator中执行)
// bool controlKey = processFog() || processPrecipitationEffect() || processSceneLight() || processSpotLamp() || processMap();//需要改回2020年9月21日15:11:59
bool controlKey = processMap();
if (controlKey)
{
break;
}
else if (processPlayCar())
{
break;
}
else
{
break;
}
m_key = -10000;
}
break;
default:
break;
}
return true;
}
//更新场景数据
void CMyEventCallback::updateScene()
{
processMenu();
//更新汽车位置
m_position = m_playCar->getPosition();
changePosition(osg::Vec3d(-m_speed*sin(m_rotatef), m_speed*cos(m_rotatef), 0.0));//做碰撞检测
m_playCar->setPosition(m_position);
//更新车灯位置
m_SpotLamp->setPosition(m_position);
//更新摄像机位置
if (m_theThreeView) //判断是否处于第三人称视角(为真是是第三人称)
{
m_cameraPos = m_position + osg::Vec3f(0, -100, 35)*osg::Matrixd(osg::Quat(m_rotatef, osg::Z_AXIS));
}
else
{
m_cameraPos = m_position + osg::Vec3f(-5, -2.2, 19)*osg::Matrixd(osg::Quat(m_rotatef, osg::Z_AXIS));
}
m_camera->setPosition(m_cameraPos);
//更新速度显示器位置
m_speedNode->setPosition(m_position);
//更新方向显示器位置
m_compassNode->setPosition(m_position);
//更新帮助节点的位置
if (m_DisplayHelp)
{
osg::Quat quat(m_camera->getRotatefX() - osg::PI_2, osg::Vec3(1.0f, 0.0f, 0.0f),m_camera->getRotatefY(), osg::Vec3(0.0f, 1.0f, 0.0f),m_camera->getRotatefZ(), osg::Vec3(0.0f, 0.0f, 1.0f));
m_helpNode->setAttitude(quat);
m_helpNode->setPosition(m_cameraPos + osg::Vec3(-15.0f, 40.0f, -7.0f)*osg::Matrixd(quat));
}
else
{
m_helpNode->setPosition(osg::Vec3(0.0f, 0.0f, -1000.0f)); //此时把该节点的位置设置到视线外
}
}
//碰撞检测,判断汽车是否能够移动
void CMyEventCallback::changePosition(osg::Vec3d delta)
{
if (m_speed > -0.05f && m_speed < 0.05f)
return;
if (m_speed < 0.0f) //倒车时的碰撞检测没有实现
{
m_position += delta;
return;
}
osg::BoundingSphere bs = m_playCar->getBound();
float radius = bs.radius() / 10;//此处包围盒的半径并不会随着pat节点的放大、缩小而变化,是固定的
float downRotatef = m_rotatef + osg::PI_4 / 3;
float upRotatef = m_rotatef - osg::PI_4 / 3;
osg::Vec3 midStart; //中间的直线段的起点
osg::Vec3 downStart; //下面的直线段的起点
osg::Vec3 upStart; //上面的直线段的起点
// if (m_speed > 0.0f)
// {
midStart = osg::Vec3(bs.center().x() - radius*sin(m_rotatef),
bs.center().y() + radius*cos(m_rotatef), bs.center().z());
downStart = osg::Vec3(bs.center().x() - radius*sin(downRotatef),
bs.center().y() + radius*cos(downRotatef), bs.center().z());
upStart = osg::Vec3(bs.center().x() - radius*sin(upRotatef),
bs.center().y() + radius*cos(upRotatef), bs.center().z());
//}
//else //倒车时候的碰撞检测,被注释了
//{
// midStart = osg::Vec3(bs.center().x()+radius*sin(m_rotatef),
// bs.center().y()-radius*cos(m_rotatef), bs.center().z());
// downStart = osg::Vec3(bs.center().x()+radius*sin(downRotatef),
// bs.center().y()-radius*cos(downRotatef), bs.center().z());
// upStart = osg::Vec3(bs.center().x()+radius*sin(upRotatef),
// bs.center().y()-radius*cos(upRotatef), bs.center().z());
//}
osg::ref_ptr<osgUtil::LineSegmentIntersector> midIntersector = new osgUtil::LineSegmentIntersector
(midStart, midStart + delta);
osg::ref_ptr<osgUtil::LineSegmentIntersector> downIntersector = new osgUtil::LineSegmentIntersector
(downStart, downStart + delta);
osg::ref_ptr<osgUtil::LineSegmentIntersector> upIntersector = new osgUtil::LineSegmentIntersector
(upStart, upStart + delta);
osgUtil::IntersectionVisitor mindIntersectVisitor(midIntersector.get());
osgUtil::IntersectionVisitor downIntersectVisitor(downIntersector.get());
osgUtil::IntersectionVisitor upIntersectVisitor(upIntersector.get());
m_rootNode->accept(mindIntersectVisitor);
m_rootNode->accept(downIntersectVisitor);
m_rootNode->accept(upIntersectVisitor);
if (midIntersector->containsIntersections()||downIntersector->containsIntersections()||upIntersector->containsIntersections())
{
//只要有任何一条线段发生了碰撞,即判定汽车与场景碰撞,此时汽车无法前行
}
else
{
m_position += delta;
}
}
//处理雾效
bool CMyEventCallback::processFog()
{
switch (m_key)
{
case '1':
m_fog->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); //雾的颜色设置为纯白色
return true;
case '2':
m_fog->setColor(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); //雾的颜色设置为纯黑色
return true;
case '3':
m_fog->setColor(osg::Vec4(0.5f, 0.5f, 0.5f, 1.0f)); //雾的颜色设置为灰色
return true;
case '9':
if (m_fogFlag = !m_fogFlag) //开启/关闭雾效
{
m_rootNode->getOrCreateStateSet()->setMode(GL_FOG, osg::StateAttribute::OFF);
}
else
{
m_rootNode->getOrCreateStateSet()->setMode(GL_FOG, osg::StateAttribute::ON);
}
return true;
default:
return false;
}
return false;
}
//处理整个驾驶地图
bool CMyEventCallback::processMap()
{
static bool isFullScreen = false;
switch (m_key)
{
case osgGA::GUIEventAdapter::KEY_F1:
if (m_DisplayHelp = !m_DisplayHelp)
{
gHelp = true;
m_theThreeView = true; // 当需要显示帮助时,驾驶视角将处于第三人称角度
}
else
{
gHelp = false;
}
return true;
case osgGA::GUIEventAdapter::KEY_F3: //全屏/窗口 模式切换
if (isFullScreen = !isFullScreen)
{
m_gw->setWindowDecoration(false); //隐藏标题栏
m_gw->setWindowRectangle(0, 0, m_screenWidth, m_screenHeight);
}
else
{
m_gw->setWindowDecoration(true); //显示标题栏
m_gw->setWindowRectangle(m_screenX, m_screenY, m_screenWindowWidth, m_screenWindowHeight);
}
return true;
case osgGA::GUIEventAdapter::KEY_F4:
m_playCar->setPosition(osg::Vec3(-60.0, -800.0, 0.0)); //汽车的位置重置到原点
return true;
default:
return false;
}
return false;
}
//控制汽车移动
bool CMyEventCallback::processPlayCar()
{
bool changeSpeed = false;
bool changeRotatef = false;
unsigned int curtime = GetTickCount();
switch (m_key)
{
case 'I':
changeSpeed = true;
m_speed += 0.2f;
break;
case 'K':
changeSpeed = true;
m_speed -= 0.2f;
break;
case 'J':
changeRotatef = true;
m_rotatef += 0.02f;
break;
case 'L':
changeRotatef = true;
m_rotatef -= 0.02f;
break;
case 'O':
changeSpeed = true;
m_speed = 0.0f;
break;
case osgGA::GUIEventAdapter::KEY_Space:
if (!(m_theThreeView = !m_theThreeView))
{
m_DisplayHelp = false;
}
break;
default:
break;
}
//如果汽车的旋转角度发生了变化,更新汽车、车灯、速度显示器、方向显示器、摄像机的旋转角度//保证其他东西也一起动起来
if (changeRotatef)
{
osg::Quat quat = osg::Quat(m_rotatef - osg::PI_2, osg::Z_AXIS);
m_playCar->setAttitude(quat);
m_SpotLamp->setAttitude(quat);
m_speedNode->setAttitude(osg::Quat(m_rotatef, osg::Z_AXIS));
m_compass->setAttitude(osg::Quat(m_rotatef, osg::Z_AXIS));
m_compassNode->setAttitude(osg::Quat(m_rotatef, osg::Z_AXIS));
m_camera->setRotatefZ(m_rotatef);
//设置汽车风向与行驶方向相等
m_precipitationEffect->setWind(osg::Vec3d(-m_speed*sin(m_rotatef), m_speed*cos(m_rotatef), 0.0));
}
//如果汽车的速度发生了变化,更新速度显示器的内容
if (changeSpeed)
{
float speed = ((int)(m_speed * 3600 * 30 / 1000)) / 20;
char text[12];
sprintf_s(text, "%.1f", speed);
string label(text);
label += " Km/h";
m_speedText->setText(label);
//设置粒子风向与汽车行驶方向相等
m_precipitationEffect->setWind(osg::Vec3d(-m_speed*sin(m_rotatef), m_speed*cos(m_rotatef), 0.0));
}
return false;
}
//控制雨雪效果
bool CMyEventCallback::processPrecipitationEffect()
{
switch (m_key)
{
case '3':
m_precipitationEffect->rain(0.0f);
return true;
case '4':
m_precipitationEffect->snow(0.001f);
m_precipitationEffect->rain(0.5f);
return true;
case '5':
m_precipitationEffect->snow(0.0f);
return true;
case '6':
m_precipitationEffect->rain(0.001f);
m_precipitationEffect->snow(0.5f);
m_precipitationEffect->setCellSize(osg::Vec3(2.0f, 2.0f, 2.0f));
return true;
default:
return false;
}
return false;
}
//控制车灯
bool CMyEventCallback::processSpotLamp()
{
static bool isOpen = true;
switch (m_key)
{
case osgGA::GUIEventAdapter::KEY_F2:
if (isOpen = !isOpen) //车灯是否开启/关闭
{
m_rootNode->getOrCreateStateSet()->setMode(GL_LIGHT1, osg::StateAttribute::OFF);
}
else
{
m_rootNode->getOrCreateStateSet()->setMode(GL_LIGHT1, osg::StateAttribute::ON);
}
return true;
default:
return false;
}
return false;
}
bool CMyEventCallback::processSceneLight()
{
static bool isNight = false;
switch (m_key)
{
case '7':
if (isNight = !isNight) //控制场景为白天/黑夜
{
m_sceneLight->setAmbient(osg::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
m_sceneLight->setDiffuse(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
m_sceneLight->setSpecular(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
}
else
{
m_sceneLight->setAmbient(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
m_sceneLight->setDiffuse(osg::Vec4(0.25f, 0.25f, 0.25f, 1.0f));
m_sceneLight->setSpecular(osg::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
}
return true;
default:
return false;
}
return false;
}
void CMyEventCallback::processMenu()
{
if (!gMousePush)
return;
gMousePush = false;
if (gSnow && gRain) //雪
{
m_precipitationEffect->snow(0.5f);
m_precipitationEffect->rain(0.5f);
}
else if (gSnow && !gRain)
{
m_precipitationEffect->rain(0.001f);
m_precipitationEffect->snow(0.5f);
}
else if (!gSnow && gRain)
{
m_precipitationEffect->snow(0.001f);
m_precipitationEffect->rain(0.5f);
}
else
{
m_precipitationEffect->rain(0.0f);
m_precipitationEffect->snow(0.0f);
}
if (gFog) //雾
{
m_rootNode->getOrCreateStateSet()->setMode(GL_FOG, osg::StateAttribute::ON);
}
else
{
m_rootNode->getOrCreateStateSet()->setMode(GL_FOG, osg::StateAttribute::OFF);
}
if (gNight) //夜晚
{
m_sceneLight->setAmbient(osg::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
m_sceneLight->setDiffuse(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
m_sceneLight->setSpecular(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
}
else
{
m_sceneLight->setAmbient(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
m_sceneLight->setDiffuse(osg::Vec4(0.25f, 0.25f, 0.25f, 1.0f));
}
if (gHelp) //帮助
{
m_DisplayHelp = true;
m_theThreeView = true;
}
else
{
m_DisplayHelp = false;
}
if (gFullScreen) //是否全屏
{
m_gw->setWindowDecoration(false);
m_gw->setWindowRectangle(0, 0, m_screenWidth, m_screenHeight);
}
else
{
m_gw->setWindowDecoration(true);
m_gw->setWindowRectangle(m_screenX, m_screenY, m_screenWindowWidth, m_screenWindowHeight);
}
}
2)MyEventCallback.h的内容
#pragma once
#include "Include.h"
#include "NodeVisitor.h"
#include "MyCamera.h"
class CMyEventCallback : /*public osg::NodeCallback:*/ public osgGA::GUIEventHandler
{
public:
CMyEventCallback(bool auto_Drive);
~CMyEventCallback();
void init(osg::Node* node, osg::NodeVisitor* nv); //初始化类中成员变量
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
void updateScene(); //更新场景数据
bool processFog(); //控制雾效
bool processPlayCar(); //控制汽车行驶
bool processPrecipitationEffect(); //控制雨雪效果
bool processSceneLight(); //控制全局光源的各项参数
bool processSpotLamp(); //控制车灯参数
bool processMap(); //控制地图
void processMenu(); //处理鼠标点击菜单
void changePosition(osg::Vec3d delta); //碰撞检测,判断汽车是否能够前进
bool m_flag_Auto_Drive; //控制是否为自动驾驶(即自动运行,键盘操作无效)
private:
//场景的根节点
osg::Group *m_rootNode;
//当前的键盘按键的键值
int m_key;
//用于控制整个窗口
osgViewer::GraphicsWindow *m_gw;
//全屏的大小
unsigned int m_screenWidth;
unsigned int m_screenHeight;
//非全屏时,程序窗口的起始位置和宽、高
unsigned int m_screenX;
unsigned int m_screenY;
unsigned int m_screenWindowWidth;
unsigned int m_screenWindowHeight;
//场景中的摄像机
CMyCamera *m_camera;
//雾效开启/关闭标志 以及 雾效状态
bool m_fogFlag;
osg::Fog *m_fog;
//雨雪节点
osgParticle::PrecipitationEffect *m_precipitationEffect;
//整个场景的全局光源
osg::Light *m_sceneLight;
//显示汽车行驶方向的 方向显示器节点
osg::PositionAttitudeTransform *m_compass;
osg::PositionAttitudeTransform *m_compassNode;
//显示汽车行驶速度的 文本节点
osgText::Text *m_speedText;
osg::PositionAttitudeTransform *m_speedNode;
//车灯
osg::PositionAttitudeTransform *m_SpotLamp;
//整个驾驶地图
osg::PositionAttitudeTransform *m_map;
//当前汽车在场景的位置 以及 摄像机的位置
osg::Vec3 m_position;
osg::Vec3 m_cameraPos;
//汽车的行驶速度 以及 汽车绕整个场景Z轴的旋转角度
float m_speed;
float m_rotatef;
//是否处于第三人称视角驾驶汽车
bool m_theThreeView;
//用于控制汽车行驶的节点
osg::PositionAttitudeTransform *m_playCar;
//用于显示帮助菜单
osg::PositionAttitudeTransform *m_helpNode;
bool m_DisplayHelp;
//用来记录按下转弯键时的时间
deque<unsigned int> m_rotatefTime;
};
class CMyViewerHandler : public osgGA::GUIEventHandler
{
public:
CMyViewerHandler() {};
~CMyViewerHandler() {};
//重载此函数,目的是为了覆盖OSG本身自带的某些键盘交互键
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
return true;
};
private:
};
(3)相机控制类:CMyCamera
1)CMyCamera.h的部分内容
#pragma once
#include "Include.h"
class CMyCamera : public osgGA::CameraManipulator,public EarthManipulator
{
public:
CMyCamera(void);
~CMyCamera(void);
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);//主要事件控制器
};
2)CMyCamera.h的部分内容
//******************************************************************
//function description: 事件控制器
//
bool CMyCamera::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
{
if (ea.getEventType() == osgGA::GUIEventAdapter::FRAME)
{
osg::Timer_t time = osg::Timer::instance()->tick();
double delta = osg::Timer::instance()->delta_s(_lastFrameTime, time);
_lastFrameTime = time;
if ( _delta >= _interval)
{
if(0) /*do something Here......*/
{
coutforFrame++;
cout << "preFrame: " << coutforFrame << endl;
//m_vRotation._v[0] += 0.015f;//单帧中做姿态转换
m_vPosition.x() = m_vPosition.x() + 20;//单帧中做位置变换
m_vPosition.y() = m_vPosition.y() + 20;
m_vPosition.z() = m_vPosition.z() + 20;
}
_delta = 0.0f;
}
else
{
_delta += delta;
}
return true;
}
switch (ea.getEventType())
{
case (osgGA::GUIEventAdapter::KEYDOWN): //如果是鼠标按下事件
{
if (ea.getKey() == 'A') //左转
{
m_fMyRotateZ += osg::DegreesToRadians(m_fAngle);
resetRotateZ();
}
if (ea.getKey() == 'D') //右转
{
m_fMyRotateZ -= osg::DegreesToRadians(m_fAngle);
resetRotateZ();
}
if (ea.getKey() == 'W') //抬头看
{
m_vRotation._v[0] += 0.015f;
return true;
}
if (ea.getKey() == 'S') //低头看
{
m_vRotation._v[0] -= 0.015f;
return true;
}
}
}
return false;
}
(4)CMyViewerHandler类:保证自身的键鼠操作不被执行,而是按照自行设置的键鼠操作,避免冲突
class CMyViewerHandler : public osgGA::GUIEventHandler
{
public:
CMyViewerHandler() {};
~CMyViewerHandler() {};
//重载此函数,目的是为了覆盖OSG本身自带的某些键盘交互键
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
return true;
};
private:
};