http://blog.csdn.net/tinya0913/article/details/6124167
效果很不错哦,希望在android上可以实现。
/**********************************************************
*Write by xuhy
**********************************************************/
#pragma once
#include <osgViewer/Viewer>
#include <osg/LineSegment>
#include <osg/Point>
#include <osg/Geometry>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Vec3>
#include <osgGA/CameraManipulator>
#include <osgUtil/IntersectVisitor>
#include <vector>
class PersonWalkManipulator :
public osgGA::CameraManipulator
{
public:
//构造函数
PersonWalkManipulator ();
PersonWalkManipulator (osg::ref_ptr <osgViewer::Viewer> viewer);
//析构函数
~PersonWalkManipulator(void);
// 把漫游加入到场景之中
static PersonWalkManipulator* TravelToScene(osg::ref_ptr <osgViewer::Viewer> viewer);
private:
osg::ref_ptr <osgViewer::Viewer> m_pHostViewer;
//移动速度
float m_fMoveSpeed;
//
osg::Vec3 m_vPosition;
//
osg::Vec3 m_vRotation;
public:
//鼠标左键是否按下
bool m_bLeftButtonDown ;
//鼠标X,Y
float m_fpushY;
float m_fpushX;
//设置矩阵
virtual void setByMatrix(const osg::Matrixd& matrix);
//设置逆矩阵
virtual void setByInverseMatrix(const osg::Matrixd& matrix);
//得到矩阵
virtual osg::Matrixd getMatrix(void) const;
//得到逆矩阵
virtual osg::Matrixd getInverseMatrix(void)const ;
//事件处理函数
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);
// 屏幕角度
float m_fAngle;
// 位置变换函数
void ChangePosition(osg::Vec3& delta);
//碰撞检测是否开启
bool m_bPeng;
//设置速度
float getSpeed() ;
void setSpeed(float &) ;
//设置起始位置
void SetPosition(osg::Vec3 &position) ;
osg::Vec3 GetPosition() ;
} ;
/**********************************************************
*Write by xuhy
**********************************************************/
#include "PersonWalkManipulator.h"
//构造函数
PersonWalkManipulator::PersonWalkManipulator(): m_fMoveSpeed(0.3f)
, m_bLeftButtonDown(false)
, m_fpushX(0)
, m_fAngle(2.5)
, m_bPeng(true)
, m_fpushY(0)
{
m_vPosition = osg::Vec3(0.0f, 0.0f, 1.7f);
m_vRotation = osg::Vec3(osg::PI_2, 0.0f, 0.0f);
}
PersonWalkManipulator::PersonWalkManipulator (osg::ref_ptr <osgViewer::Viewer> viewer): m_fMoveSpeed(0.3f)
, m_bLeftButtonDown(false)
, m_fpushX(0)
, m_fAngle(2.5)
, m_bPeng(true)
, m_fpushY(0)
{
m_vPosition = osg::Vec3(0.0f, 0.0f, 1.7f);
m_vRotation = osg::Vec3(osg::PI_2, 0.0f, 0.0f);
m_pHostViewer = viewer;
//计算立足点的z值
osg::ref_ptr<osg::LineSegment> lineZ = new osg::LineSegment(m_vPosition,
osg::Vec3(0.0f, 0.0f, 0.0f)) ;
osgUtil::IntersectVisitor findZ;
findZ.addLineSegment(lineZ.get()) ;
osg::Node* rt = m_pHostViewer->getSceneData();
if(rt){
rt->accept(findZ) ;
osgUtil::IntersectVisitor::HitList hits;
hits = findZ.getHitList(lineZ.get());
osgUtil::Hit newPositionResult;
if ( !hits.empty() )
{
newPositionResult = hits.front();
osg::Vec3 newPos = newPositionResult.getWorldIntersectPoint();
m_vPosition =newPos + osg::Vec3(0.0,0.0,1.7f) ;
}
}
}
//析构函数
PersonWalkManipulator::~PersonWalkManipulator()
{
//
}
// 把漫游加入到场景之中
PersonWalkManipulator * PersonWalkManipulator::TravelToScene(osg::ref_ptr <osgViewer::Viewer> viewer)
{
PersonWalkManipulator* camera = new PersonWalkManipulator;
viewer->setCameraManipulator(camera) ;
camera->m_pHostViewer =viewer ;
return camera;
}
// 设置矩阵
void PersonWalkManipulator::setByMatrix(const osg::Matrixd& matrix)
{
//
}
//设置逆矩阵
void PersonWalkManipulator::setByInverseMatrix(const osg::Matrixd& matrix)
{
//
}
//得到矩阵
osg::Matrixd PersonWalkManipulator::getMatrix(void) const
{
osg::Matrixd mat;
mat.makeRotate(m_vRotation._v[0], osg::Vec3(1.0f, 0.0f, 0.0f),
m_vRotation._v[1], osg::Vec3(0.0f, 1.0f, 0.0f),
m_vRotation._v[2], osg::Vec3(0.0f, 0.0f, 1.0f));
return mat * osg::Matrixd::translate(m_vPosition);
}
//得到逆矩阵
osg::Matrixd PersonWalkManipulator::getInverseMatrix(void) const
{
osg::Matrixd mat;
mat.makeRotate(m_vRotation._v[0], osg::Vec3(1.0f, 0.0f, 0.0f),
m_vRotation._v[1], osg::Vec3(0.0f, 1.0f, 0.0f),
m_vRotation._v[2], osg::Vec3(0.0f, 0.0f, 1.0f));
return osg::Matrixd::inverse(mat * osg::Matrixd::translate(m_vPosition));
}
//事件处理函数
bool PersonWalkManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
{
//得到鼠标的位置
float mouseX = ea.getX();
float mouseY = ea.getY();
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYDOWN):
{
//空格键
if (ea.getKey() == 0x20)
{
us.requestRedraw();
us.requestContinuousUpdate(false);
return true;
}
//上移动
if (ea.getKey() == 0xFF50)
{
osg::Vec3 up(0, 0, m_fMoveSpeed);
osg::Vec3& r_up = up;
ChangePosition(r_up) ;
return true;
}
//下移动
if (ea.getKey() == 0xFF57)
{
osg::Vec3 down(0, 0, -m_fMoveSpeed);
osg::Vec3& r_down = down;
ChangePosition(r_down) ;
return true;
}
//增加速度 右键
if (ea.getKey() == 0x2B)
{
m_fMoveSpeed += 0.3f;
return true;
}
//减少速度
if (ea.getKey() == 0x2D)
{
m_fMoveSpeed -= 0.3f;
if (m_fMoveSpeed < 0.3f)
{
m_fMoveSpeed = 0.3f;
}
return true;
}
//前进
if (ea.getKey() == 0xFF52 || ea.getKey () == 0x57 || ea.getKey () == 0x77)//up,w,f8
{
osg::Vec3 v1(0, m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0);
osg::Vec3& r_v1 = v1;
ChangePosition(r_v1) ;
osg::Vec3 v2(m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0, 0);
osg::Vec3& r_v2 = v2;
ChangePosition(r_v2) ;
return true;
}
//后退
if (ea.getKey() == 0xFF54 || ea.getKey () == 0x53 || ea.getKey () == 0x73 )//down s f4
{
osg::Vec3 v1(0, -m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0);
osg::Vec3& r_v1 = v1;
ChangePosition(r_v1) ;
osg::Vec3 v2(-m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0, 0);
osg::Vec3& r_v2 = v2;
ChangePosition(r_v2) ;
return true;
}
//向左
if (ea.getKey () == 0x41||ea.getKey () == 0x61)//a 数字键1
{
osg::Vec3 v1(0, m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0);
osg::Vec3& r_v1 = v1;
ChangePosition(r_v1) ;
osg::Vec3 v2(-m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0, 0);
osg::Vec3& r_v2 = v2;
ChangePosition(r_v2) ;
return true;
}
//向右
if (ea.getKey () == 0x44||ea.getKey () == 0x64) //d 数字键4
{
osg::Vec3 v1(0,-m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0);
osg::Vec3& r_v1 = v1;
ChangePosition(r_v1) ;
osg::Vec3 v2(m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0, 0);
osg::Vec3& r_v2 = v2;
ChangePosition(r_v2) ;
return true;
}
//Right
if (ea.getKey() == 0xFF53)//右方向键
{
m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle);
}
//Left
if (ea.getKey()== 0xFF51)
{
m_vRotation._v[2] += osg::DegreesToRadians(m_fAngle);
}
//改变屏角
if (ea.getKey() == 0x46 || ea.getKey() == 0x66)//F 数字键6
{
m_fAngle -= 0.2 ;
if(m_fAngle<0.2)
{
m_fAngle = 0.2;
}
return true ;
}
if (ea.getKey() == 0x47 || ea.getKey() == 0x67)//G 数字键7
{
m_fAngle += 0.2 ;
if(m_fAngle>2.5)
{
m_fAngle = 2.5;
}
return true ;
}
return false;
}
//鼠标按下
case (osgGA::GUIEventAdapter ::PUSH ):
osg::notify(osg::ALWAYS)<<"PUSH";
osg::notify(osg::ALWAYS)<<ea.getButton ()<<std::endl;
if ( ea.getButton () == 1)
{
osg::notify(osg::ALWAYS)<<"1 PUSH"<<std::endl;
m_fpushX = mouseX ;
m_fpushY = mouseY ;
m_bLeftButtonDown = true ;
}
return false ;
//拖动
case (osgGA::GUIEventAdapter ::DRAG ):
osg::notify(osg::ALWAYS)<<"drag";
osg::notify(osg::ALWAYS)<<m_bLeftButtonDown<<std::endl;
if ( m_bLeftButtonDown)
{
osg::notify(osg::ALWAYS)<<"left drag"<<std::endl;
m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle * (mouseX - m_fpushX)) / 1000;
m_vRotation._v[0] += osg::DegreesToRadians(m_fAngle * (mouseY - m_fpushY)) / 1000;
if (m_vRotation._v [0] >= 3.14)
{
m_vRotation._v [0] = 3.14 ;
}
if (m_vRotation._v [0] <= 0)
{
m_vRotation._v [0] = 0 ;
}
}
return false ;
//鼠标释放
case (osgGA::GUIEventAdapter ::RELEASE ):
osg::notify(osg::ALWAYS)<<"release"<<std::endl;
if ( ea.getButton () == 1)
{
m_bLeftButtonDown = false ;
}
return false ;
default:
return false;
}
}
// 位置变换函数
void PersonWalkManipulator::ChangePosition(osg::Vec3& delta)
{
//
if (m_bPeng)
{
//得到新的位置
osg::Vec3 newPos1 = m_vPosition + delta;
//新位置合理性检测,新位置以下1.0米开始,1.4米的范围
osg::ref_ptr<osg::LineSegment> lineZ = new osg::LineSegment(osg::Vec3(newPos1.x(),newPos1.y(),newPos1.z()-1.0f),
osg::Vec3(newPos1.x(),newPos1.y(),newPos1.z()-2.4f)) ;
osgUtil::IntersectVisitor findZ;
findZ.addLineSegment(lineZ.get()) ;
m_pHostViewer->getSceneData()->accept(findZ) ;
osgUtil::IntersectVisitor::HitList hits;
hits =
findZ.getHitList(lineZ.get());
osgUtil::Hit newPositionResult;
if ( !hits.empty() )
{
newPositionResult = hits.front();
osg::Vec3 newPos = newPositionResult.getWorldIntersectPoint();
newPos += osg::Vec3(0.0,0.0,1.7f) ;
//检查新位置是否够1.7米
lineZ = new osg::LineSegment(newPos,newPos-osg::Vec3(0.0,0.0,1.69f) );
osgUtil::IntersectVisitor findNewZ;
findNewZ.addLineSegment(lineZ.get()) ;
m_pHostViewer->getSceneData()->accept(findNewZ) ;
hits = findNewZ.getHitList(lineZ.get());
if ( hits.empty() )//表示新位置够1.7米
{
//检查是否遮挡
lineZ = new osg::LineSegment(m_vPosition,newPos);
osgUtil::IntersectVisitor findWall;
findWall.addLineSegment(lineZ.get()) ;
m_pHostViewer->getSceneData()->accept(findWall) ;
hits = findWall.getHitList(lineZ.get());
if ( hits.empty() )//表示没有遮挡
{
m_vPosition=newPos;
}else
{
newPositionResult = hits.front();
osg::Vec3 newPos3 = newPositionResult.getWorldIntersectPoint();
osg::notify(osg::ALWAYS)<<newPos3.x()<<","<<newPos3.y()<<","<<newPos3.z()<<std::endl;
}
}else
{
newPositionResult = hits.front();
osg::Vec3 newPos2 = newPositionResult.getWorldIntersectPoint();
osg::notify(osg::ALWAYS)<<newPos2.x()<<","<<newPos2.y()<<","<<newPos2.z()<<std::endl;
}
}
}
else
{
m_vPosition += delta;
}
/*
//碰撞检测
if (m_bPeng)
{
//得到新的位置
osg::Vec3 newPos1 = m_vPosition + delta;
osgUtil::IntersectVisitor ivXY;
//根据新的位置得到两条线段检测
osg::ref_ptr<osg::LineSegment> lineXY = new osg::LineSegment(newPos1,
m_vPosition);
osg::ref_ptr<osg::LineSegment> lineZ = new osg::LineSegment(newPos1,
newPos1 + osg::Vec3(0.0f,0.0f,-0.5f)) ;
ivXY.addLineSegment(lineZ.get()) ;
ivXY.addLineSegment(lineXY.get()) ;
//结构交集检测
m_pHostViewer->getSceneData()->accept(ivXY) ;
//如果没有碰撞检测
if(!ivXY.hits())
{
m_vPosition += delta;
}
}
else
{
m_vPosition += delta;
}
*/
}
//设置速度
void PersonWalkManipulator::setSpeed (float &sp)
{
m_fMoveSpeed = sp ;
}
//得到当前速度
float PersonWalkManipulator::getSpeed()
{
return m_fMoveSpeed ;
}
//设置起始的位置
void PersonWalkManipulator::SetPosition (osg::Vec3 &position)
{
m_vPosition = position ;
}
//得到当前的所在位置
osg::Vec3 PersonWalkManipulator::GetPosition ()
{
return m_vPosition ;
}
/* OpenSceneGraph example, osglight.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <osgViewer/Viewer>
#include <osg/Group>
#include <osg/Node>
#include <osg/Light>
#include <osg/LightSource>
#include <osg/StateAttribute>
#include <osg/Geometry>
#include <osg/Point>
#include <osg/BlendFunc>
#include <osg/PointSprite>
#include <osg/ShapeDrawable>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/GUIEventAdapter>
#include <osgGA/MultiTouchTrackballManipulator>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osgGA/SphericalManipulator>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osgUtil/SmoothingVisitor>
#include "stdio.h"
#include "PersonWalkManipulator.h"
osg::StateSet* makeStateSet(float size)
{
osg::StateSet *set = new osg::StateSet();
///// Setup cool blending
//set->setMode(GL_BLEND, osg::StateAttribute::ON);
//osg::BlendFunc *fn = new osg::BlendFunc();
//fn->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::DST_ALPHA);
//set->setAttributeAndModes(fn, osg::StateAttribute::ON);
/// Setup the point sprites
osg::PointSprite *sprite = new osg::PointSprite();
set->setTextureAttributeAndModes(0, sprite, osg::StateAttribute::ON);
/// Give some size to the points to be able to see the sprite
osg::Point *point = new osg::Point();
point->setSize(size);
set->setAttribute(point);
// Disable depth test to avoid sort problems and Lighting
//set->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
set->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
///// The texture for the sprites
//osg::Texture2D *tex = new osg::Texture2D();
//tex->setImage(osgDB::readImageFile("Images/particle.rgb"));
//set->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
return set;
}
osg::Node* createLights(osg::BoundingBox& bb,osg::StateSet* rootStateSet)
{
osg::Group* lightGroup = new osg::Group;
float modelSize = bb.radius();
// create a spot light.
osg::Light* myLight1 = new osg::Light;
myLight1->setLightNum(0);
myLight1->setPosition(osg::Vec4(bb.corner(4),1.0f));//设置位置,第四个参数为0表示平行光
myLight1->setAmbient(osg::Vec4(0.5f,0.5f,0.5f,1.0f));//设置环境光的颜色,第四个设为1,透明度
myLight1->setDiffuse(osg::Vec4(1.0f,1.0f,1.0f,1.0f));//设置散射光的颜色
//myLight1->setSpotCutoff(20.0f);// 聚光灯圆锥的顶角
//myLight1->setSpotExponent(100.0f);// 聚光指数
myLight1->setDirection(osg::Vec3(1.0f,1.0f,-1.0f));//设置方向
osg::LightSource* lightS1 = new osg::LightSource;
lightS1->setLight(myLight1);
lightS1->setLocalStateSetModes(osg::StateAttribute::ON);
lightS1->setStateSetModes(*rootStateSet,osg::StateAttribute::ON);
lightGroup->addChild(lightS1);
osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Sphere(bb.center(), 0.2));
osg::Geode* lightNode = new osg::Geode;
lightNode->addDrawable(sd);
lightNode->getOrCreateStateSet()->setTextureAttributeAndModes(0, new osg::Texture2D(osgDB::readImageFile("Images/land_shallow_topo_2048.jpg")));
lightGroup->addChild(lightNode);
return lightGroup;
}
osg::ref_ptr<osg::Geode> makeCoordinate()
{
//创建保存几何信息的对象
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, 0.0f, 0.0f));
v->push_back(osg::Vec3(1000.0f, 0.0f, 0.0f));
v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
v->push_back(osg::Vec3(0.0f, 1000.0f, 0.0f));
v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
v->push_back(osg::Vec3(0.0f, 0.0f, 1000.0f));
geom->setVertexArray(v.get());
//为每个顶点指定一种颜色
osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array();
c->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); //坐标原点为红色
c->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); //x red
c->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); //坐标原点为绿色
c->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); //y green
c->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); //坐标原点为蓝色
c->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); //z blue
//如果没指定颜色则会变为黑色
geom->setColorArray(c.get());
geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
//三个轴
geom->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, 2)); //X LINES表示两个一组,第一个点和个数
geom->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::LINES, 2, 2)); //Y
geom->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::LINES, 4, 2)); //Z
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
geode->addDrawable(geom.get());
return geode;
}
int main( int argc, char **argv )
{
osg::Node* _roomNode = osgDB::readNodeFile("room.ive");
// create a room made of foor walls, a floor, a roof, and swinging light fitting.
osg::ref_ptr<osg::Group> root = new osg::Group();
root->addChild(_roomNode);
osg::BoundingSphere bs = _roomNode->getBound();
osg::BoundingBox bb;
bb.expandBy(bs);
osg::ref_ptr<osg::StateSet> _state = root->getOrCreateStateSet();
_state->setMode(GL_LIGHTING, osg::StateAttribute::ON);
root->addChild( createLights(bb,_state));
root->addChild(makeCoordinate().get());
// run optimization over the scene graph
osgUtil::Optimizer optimzer;
optimzer.optimize(root.get());
osg::ref_ptr<osgViewer::Viewer> _viewer= new osgViewer::Viewer();
_viewer->setUpViewInWindow(50, 50, 800, 600);
//把漫游器加入到场景中
/*PersonWalkManipulator::TravelToScene(viewer.get());*/
//_viewer->addEventHandler(new osgViewer::StatsHandler);
_viewer->addEventHandler(new osgGA::StateSetManipulator(_viewer->getCamera()->getOrCreateStateSet()));
//_viewer->addEventHandler(new osgViewer::ThreadingHandler);
//_viewer->addEventHandler(new osgViewer::LODScaleHandler);
// add a viewport to the viewer and attach the scene graph.
_viewer->setSceneData( root.get() );
osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> _manipulator = new osgGA::KeySwitchMatrixManipulator;
PersonWalkManipulator* pm = new PersonWalkManipulator(_viewer);
osgGA::TerrainManipulator* tm = new osgGA::TerrainManipulator();
_manipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
_manipulator->addMatrixManipulator( '2', "FirstPerson", pm );
_manipulator->addMatrixManipulator( '3', "Flight", new osgGA::FlightManipulator() );
_manipulator->addMatrixManipulator( '4', "Drive", new osgGA::DriveManipulator() );
_manipulator->addMatrixManipulator( '5', "Terrain",tm );
_manipulator->addMatrixManipulator( '6', "Orbit", new osgGA::OrbitManipulator() );
_manipulator->addMatrixManipulator( '7', "FirstPerson", new osgGA::FirstPersonManipulator() );
_manipulator->addMatrixManipulator( '8', "Spherical", new osgGA::SphericalManipulator() );
_viewer->setCameraManipulator( _manipulator.get() );
// create the windows and run the threads.
_viewer->realize();
_viewer->getCamera()->setCullingMode( _viewer->getCamera()->getCullingMode() & ~osg::CullStack::SMALL_FEATURE_CULLING);
return _viewer->run();
}
*Write by xuhy
**********************************************************/
#pragma once
#include <osgViewer/Viewer>
#include <osg/LineSegment>
#include <osg/Point>
#include <osg/Geometry>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Vec3>
#include <osgGA/CameraManipulator>
#include <osgUtil/IntersectVisitor>
#include <vector>
class PersonWalkManipulator :
public osgGA::CameraManipulator
{
public:
//构造函数
PersonWalkManipulator ();
PersonWalkManipulator (osg::ref_ptr <osgViewer::Viewer> viewer);
//析构函数
~PersonWalkManipulator(void);
// 把漫游加入到场景之中
static PersonWalkManipulator* TravelToScene(osg::ref_ptr <osgViewer::Viewer> viewer);
private:
osg::ref_ptr <osgViewer::Viewer> m_pHostViewer;
//移动速度
float m_fMoveSpeed;
//
osg::Vec3 m_vPosition;
//
osg::Vec3 m_vRotation;
public:
//鼠标左键是否按下
bool m_bLeftButtonDown ;
//鼠标X,Y
float m_fpushY;
float m_fpushX;
//设置矩阵
virtual void setByMatrix(const osg::Matrixd& matrix);
//设置逆矩阵
virtual void setByInverseMatrix(const osg::Matrixd& matrix);
//得到矩阵
virtual osg::Matrixd getMatrix(void) const;
//得到逆矩阵
virtual osg::Matrixd getInverseMatrix(void)const ;
//事件处理函数
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);
// 屏幕角度
float m_fAngle;
// 位置变换函数
void ChangePosition(osg::Vec3& delta);
//碰撞检测是否开启
bool m_bPeng;
//设置速度
float getSpeed() ;
void setSpeed(float &) ;
//设置起始位置
void SetPosition(osg::Vec3 &position) ;
osg::Vec3 GetPosition() ;
} ;
/**********************************************************
*Write by xuhy
**********************************************************/
#include "PersonWalkManipulator.h"
//构造函数
PersonWalkManipulator::PersonWalkManipulator(): m_fMoveSpeed(0.3f)
, m_bLeftButtonDown(false)
, m_fpushX(0)
, m_fAngle(2.5)
, m_bPeng(true)
, m_fpushY(0)
{
m_vPosition = osg::Vec3(0.0f, 0.0f, 1.7f);
m_vRotation = osg::Vec3(osg::PI_2, 0.0f, 0.0f);
}
PersonWalkManipulator::PersonWalkManipulator (osg::ref_ptr <osgViewer::Viewer> viewer): m_fMoveSpeed(0.3f)
, m_bLeftButtonDown(false)
, m_fpushX(0)
, m_fAngle(2.5)
, m_bPeng(true)
, m_fpushY(0)
{
m_vPosition = osg::Vec3(0.0f, 0.0f, 1.7f);
m_vRotation = osg::Vec3(osg::PI_2, 0.0f, 0.0f);
m_pHostViewer = viewer;
//计算立足点的z值
osg::ref_ptr<osg::LineSegment> lineZ = new osg::LineSegment(m_vPosition,
osg::Vec3(0.0f, 0.0f, 0.0f)) ;
osgUtil::IntersectVisitor findZ;
findZ.addLineSegment(lineZ.get()) ;
osg::Node* rt = m_pHostViewer->getSceneData();
if(rt){
rt->accept(findZ) ;
osgUtil::IntersectVisitor::HitList hits;
hits = findZ.getHitList(lineZ.get());
osgUtil::Hit newPositionResult;
if ( !hits.empty() )
{
newPositionResult = hits.front();
osg::Vec3 newPos = newPositionResult.getWorldIntersectPoint();
m_vPosition =newPos + osg::Vec3(0.0,0.0,1.7f) ;
}
}
}
//析构函数
PersonWalkManipulator::~PersonWalkManipulator()
{
//
}
// 把漫游加入到场景之中
PersonWalkManipulator * PersonWalkManipulator::TravelToScene(osg::ref_ptr <osgViewer::Viewer> viewer)
{
PersonWalkManipulator* camera = new PersonWalkManipulator;
viewer->setCameraManipulator(camera) ;
camera->m_pHostViewer =viewer ;
return camera;
}
// 设置矩阵
void PersonWalkManipulator::setByMatrix(const osg::Matrixd& matrix)
{
//
}
//设置逆矩阵
void PersonWalkManipulator::setByInverseMatrix(const osg::Matrixd& matrix)
{
//
}
//得到矩阵
osg::Matrixd PersonWalkManipulator::getMatrix(void) const
{
osg::Matrixd mat;
mat.makeRotate(m_vRotation._v[0], osg::Vec3(1.0f, 0.0f, 0.0f),
m_vRotation._v[1], osg::Vec3(0.0f, 1.0f, 0.0f),
m_vRotation._v[2], osg::Vec3(0.0f, 0.0f, 1.0f));
return mat * osg::Matrixd::translate(m_vPosition);
}
//得到逆矩阵
osg::Matrixd PersonWalkManipulator::getInverseMatrix(void) const
{
osg::Matrixd mat;
mat.makeRotate(m_vRotation._v[0], osg::Vec3(1.0f, 0.0f, 0.0f),
m_vRotation._v[1], osg::Vec3(0.0f, 1.0f, 0.0f),
m_vRotation._v[2], osg::Vec3(0.0f, 0.0f, 1.0f));
return osg::Matrixd::inverse(mat * osg::Matrixd::translate(m_vPosition));
}
//事件处理函数
bool PersonWalkManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
{
//得到鼠标的位置
float mouseX = ea.getX();
float mouseY = ea.getY();
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYDOWN):
{
//空格键
if (ea.getKey() == 0x20)
{
us.requestRedraw();
us.requestContinuousUpdate(false);
return true;
}
//上移动
if (ea.getKey() == 0xFF50)
{
osg::Vec3 up(0, 0, m_fMoveSpeed);
osg::Vec3& r_up = up;
ChangePosition(r_up) ;
return true;
}
//下移动
if (ea.getKey() == 0xFF57)
{
osg::Vec3 down(0, 0, -m_fMoveSpeed);
osg::Vec3& r_down = down;
ChangePosition(r_down) ;
return true;
}
//增加速度 右键
if (ea.getKey() == 0x2B)
{
m_fMoveSpeed += 0.3f;
return true;
}
//减少速度
if (ea.getKey() == 0x2D)
{
m_fMoveSpeed -= 0.3f;
if (m_fMoveSpeed < 0.3f)
{
m_fMoveSpeed = 0.3f;
}
return true;
}
//前进
if (ea.getKey() == 0xFF52 || ea.getKey () == 0x57 || ea.getKey () == 0x77)//up,w,f8
{
osg::Vec3 v1(0, m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0);
osg::Vec3& r_v1 = v1;
ChangePosition(r_v1) ;
osg::Vec3 v2(m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0, 0);
osg::Vec3& r_v2 = v2;
ChangePosition(r_v2) ;
return true;
}
//后退
if (ea.getKey() == 0xFF54 || ea.getKey () == 0x53 || ea.getKey () == 0x73 )//down s f4
{
osg::Vec3 v1(0, -m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0);
osg::Vec3& r_v1 = v1;
ChangePosition(r_v1) ;
osg::Vec3 v2(-m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0, 0);
osg::Vec3& r_v2 = v2;
ChangePosition(r_v2) ;
return true;
}
//向左
if (ea.getKey () == 0x41||ea.getKey () == 0x61)//a 数字键1
{
osg::Vec3 v1(0, m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0);
osg::Vec3& r_v1 = v1;
ChangePosition(r_v1) ;
osg::Vec3 v2(-m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0, 0);
osg::Vec3& r_v2 = v2;
ChangePosition(r_v2) ;
return true;
}
//向右
if (ea.getKey () == 0x44||ea.getKey () == 0x64) //d 数字键4
{
osg::Vec3 v1(0,-m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0);
osg::Vec3& r_v1 = v1;
ChangePosition(r_v1) ;
osg::Vec3 v2(m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0, 0);
osg::Vec3& r_v2 = v2;
ChangePosition(r_v2) ;
return true;
}
//Right
if (ea.getKey() == 0xFF53)//右方向键
{
m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle);
}
//Left
if (ea.getKey()== 0xFF51)
{
m_vRotation._v[2] += osg::DegreesToRadians(m_fAngle);
}
//改变屏角
if (ea.getKey() == 0x46 || ea.getKey() == 0x66)//F 数字键6
{
m_fAngle -= 0.2 ;
if(m_fAngle<0.2)
{
m_fAngle = 0.2;
}
return true ;
}
if (ea.getKey() == 0x47 || ea.getKey() == 0x67)//G 数字键7
{
m_fAngle += 0.2 ;
if(m_fAngle>2.5)
{
m_fAngle = 2.5;
}
return true ;
}
return false;
}
//鼠标按下
case (osgGA::GUIEventAdapter ::PUSH ):
osg::notify(osg::ALWAYS)<<"PUSH";
osg::notify(osg::ALWAYS)<<ea.getButton ()<<std::endl;
if ( ea.getButton () == 1)
{
osg::notify(osg::ALWAYS)<<"1 PUSH"<<std::endl;
m_fpushX = mouseX ;
m_fpushY = mouseY ;
m_bLeftButtonDown = true ;
}
return false ;
//拖动
case (osgGA::GUIEventAdapter ::DRAG ):
osg::notify(osg::ALWAYS)<<"drag";
osg::notify(osg::ALWAYS)<<m_bLeftButtonDown<<std::endl;
if ( m_bLeftButtonDown)
{
osg::notify(osg::ALWAYS)<<"left drag"<<std::endl;
m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle * (mouseX - m_fpushX)) / 1000;
m_vRotation._v[0] += osg::DegreesToRadians(m_fAngle * (mouseY - m_fpushY)) / 1000;
if (m_vRotation._v [0] >= 3.14)
{
m_vRotation._v [0] = 3.14 ;
}
if (m_vRotation._v [0] <= 0)
{
m_vRotation._v [0] = 0 ;
}
}
return false ;
//鼠标释放
case (osgGA::GUIEventAdapter ::RELEASE ):
osg::notify(osg::ALWAYS)<<"release"<<std::endl;
if ( ea.getButton () == 1)
{
m_bLeftButtonDown = false ;
}
return false ;
default:
return false;
}
}
// 位置变换函数
void PersonWalkManipulator::ChangePosition(osg::Vec3& delta)
{
//
if (m_bPeng)
{
//得到新的位置
osg::Vec3 newPos1 = m_vPosition + delta;
//新位置合理性检测,新位置以下1.0米开始,1.4米的范围
osg::ref_ptr<osg::LineSegment> lineZ = new osg::LineSegment(osg::Vec3(newPos1.x(),newPos1.y(),newPos1.z()-1.0f),
osg::Vec3(newPos1.x(),newPos1.y(),newPos1.z()-2.4f)) ;
osgUtil::IntersectVisitor findZ;
findZ.addLineSegment(lineZ.get()) ;
m_pHostViewer->getSceneData()->accept(findZ) ;
osgUtil::IntersectVisitor::HitList hits;
hits =
findZ.getHitList(lineZ.get());
osgUtil::Hit newPositionResult;
if ( !hits.empty() )
{
newPositionResult = hits.front();
osg::Vec3 newPos = newPositionResult.getWorldIntersectPoint();
newPos += osg::Vec3(0.0,0.0,1.7f) ;
//检查新位置是否够1.7米
lineZ = new osg::LineSegment(newPos,newPos-osg::Vec3(0.0,0.0,1.69f) );
osgUtil::IntersectVisitor findNewZ;
findNewZ.addLineSegment(lineZ.get()) ;
m_pHostViewer->getSceneData()->accept(findNewZ) ;
hits = findNewZ.getHitList(lineZ.get());
if ( hits.empty() )//表示新位置够1.7米
{
//检查是否遮挡
lineZ = new osg::LineSegment(m_vPosition,newPos);
osgUtil::IntersectVisitor findWall;
findWall.addLineSegment(lineZ.get()) ;
m_pHostViewer->getSceneData()->accept(findWall) ;
hits = findWall.getHitList(lineZ.get());
if ( hits.empty() )//表示没有遮挡
{
m_vPosition=newPos;
}else
{
newPositionResult = hits.front();
osg::Vec3 newPos3 = newPositionResult.getWorldIntersectPoint();
osg::notify(osg::ALWAYS)<<newPos3.x()<<","<<newPos3.y()<<","<<newPos3.z()<<std::endl;
}
}else
{
newPositionResult = hits.front();
osg::Vec3 newPos2 = newPositionResult.getWorldIntersectPoint();
osg::notify(osg::ALWAYS)<<newPos2.x()<<","<<newPos2.y()<<","<<newPos2.z()<<std::endl;
}
}
}
else
{
m_vPosition += delta;
}
/*
//碰撞检测
if (m_bPeng)
{
//得到新的位置
osg::Vec3 newPos1 = m_vPosition + delta;
osgUtil::IntersectVisitor ivXY;
//根据新的位置得到两条线段检测
osg::ref_ptr<osg::LineSegment> lineXY = new osg::LineSegment(newPos1,
m_vPosition);
osg::ref_ptr<osg::LineSegment> lineZ = new osg::LineSegment(newPos1,
newPos1 + osg::Vec3(0.0f,0.0f,-0.5f)) ;
ivXY.addLineSegment(lineZ.get()) ;
ivXY.addLineSegment(lineXY.get()) ;
//结构交集检测
m_pHostViewer->getSceneData()->accept(ivXY) ;
//如果没有碰撞检测
if(!ivXY.hits())
{
m_vPosition += delta;
}
}
else
{
m_vPosition += delta;
}
*/
}
//设置速度
void PersonWalkManipulator::setSpeed (float &sp)
{
m_fMoveSpeed = sp ;
}
//得到当前速度
float PersonWalkManipulator::getSpeed()
{
return m_fMoveSpeed ;
}
//设置起始的位置
void PersonWalkManipulator::SetPosition (osg::Vec3 &position)
{
m_vPosition = position ;
}
//得到当前的所在位置
osg::Vec3 PersonWalkManipulator::GetPosition ()
{
return m_vPosition ;
}
/* OpenSceneGraph example, osglight.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <osgViewer/Viewer>
#include <osg/Group>
#include <osg/Node>
#include <osg/Light>
#include <osg/LightSource>
#include <osg/StateAttribute>
#include <osg/Geometry>
#include <osg/Point>
#include <osg/BlendFunc>
#include <osg/PointSprite>
#include <osg/ShapeDrawable>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/GUIEventAdapter>
#include <osgGA/MultiTouchTrackballManipulator>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osgGA/SphericalManipulator>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osgUtil/SmoothingVisitor>
#include "stdio.h"
#include "PersonWalkManipulator.h"
osg::StateSet* makeStateSet(float size)
{
osg::StateSet *set = new osg::StateSet();
///// Setup cool blending
//set->setMode(GL_BLEND, osg::StateAttribute::ON);
//osg::BlendFunc *fn = new osg::BlendFunc();
//fn->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::DST_ALPHA);
//set->setAttributeAndModes(fn, osg::StateAttribute::ON);
/// Setup the point sprites
osg::PointSprite *sprite = new osg::PointSprite();
set->setTextureAttributeAndModes(0, sprite, osg::StateAttribute::ON);
/// Give some size to the points to be able to see the sprite
osg::Point *point = new osg::Point();
point->setSize(size);
set->setAttribute(point);
// Disable depth test to avoid sort problems and Lighting
//set->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
set->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
///// The texture for the sprites
//osg::Texture2D *tex = new osg::Texture2D();
//tex->setImage(osgDB::readImageFile("Images/particle.rgb"));
//set->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
return set;
}
osg::Node* createLights(osg::BoundingBox& bb,osg::StateSet* rootStateSet)
{
osg::Group* lightGroup = new osg::Group;
float modelSize = bb.radius();
// create a spot light.
osg::Light* myLight1 = new osg::Light;
myLight1->setLightNum(0);
myLight1->setPosition(osg::Vec4(bb.corner(4),1.0f));//设置位置,第四个参数为0表示平行光
myLight1->setAmbient(osg::Vec4(0.5f,0.5f,0.5f,1.0f));//设置环境光的颜色,第四个设为1,透明度
myLight1->setDiffuse(osg::Vec4(1.0f,1.0f,1.0f,1.0f));//设置散射光的颜色
//myLight1->setSpotCutoff(20.0f);// 聚光灯圆锥的顶角
//myLight1->setSpotExponent(100.0f);// 聚光指数
myLight1->setDirection(osg::Vec3(1.0f,1.0f,-1.0f));//设置方向
osg::LightSource* lightS1 = new osg::LightSource;
lightS1->setLight(myLight1);
lightS1->setLocalStateSetModes(osg::StateAttribute::ON);
lightS1->setStateSetModes(*rootStateSet,osg::StateAttribute::ON);
lightGroup->addChild(lightS1);
osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Sphere(bb.center(), 0.2));
osg::Geode* lightNode = new osg::Geode;
lightNode->addDrawable(sd);
lightNode->getOrCreateStateSet()->setTextureAttributeAndModes(0, new osg::Texture2D(osgDB::readImageFile("Images/land_shallow_topo_2048.jpg")));
lightGroup->addChild(lightNode);
return lightGroup;
}
osg::ref_ptr<osg::Geode> makeCoordinate()
{
//创建保存几何信息的对象
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, 0.0f, 0.0f));
v->push_back(osg::Vec3(1000.0f, 0.0f, 0.0f));
v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
v->push_back(osg::Vec3(0.0f, 1000.0f, 0.0f));
v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
v->push_back(osg::Vec3(0.0f, 0.0f, 1000.0f));
geom->setVertexArray(v.get());
//为每个顶点指定一种颜色
osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array();
c->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); //坐标原点为红色
c->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); //x red
c->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); //坐标原点为绿色
c->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); //y green
c->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); //坐标原点为蓝色
c->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); //z blue
//如果没指定颜色则会变为黑色
geom->setColorArray(c.get());
geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
//三个轴
geom->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, 2)); //X LINES表示两个一组,第一个点和个数
geom->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::LINES, 2, 2)); //Y
geom->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::LINES, 4, 2)); //Z
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
geode->addDrawable(geom.get());
return geode;
}
int main( int argc, char **argv )
{
osg::Node* _roomNode = osgDB::readNodeFile("room.ive");
// create a room made of foor walls, a floor, a roof, and swinging light fitting.
osg::ref_ptr<osg::Group> root = new osg::Group();
root->addChild(_roomNode);
osg::BoundingSphere bs = _roomNode->getBound();
osg::BoundingBox bb;
bb.expandBy(bs);
osg::ref_ptr<osg::StateSet> _state = root->getOrCreateStateSet();
_state->setMode(GL_LIGHTING, osg::StateAttribute::ON);
root->addChild( createLights(bb,_state));
root->addChild(makeCoordinate().get());
// run optimization over the scene graph
osgUtil::Optimizer optimzer;
optimzer.optimize(root.get());
osg::ref_ptr<osgViewer::Viewer> _viewer= new osgViewer::Viewer();
_viewer->setUpViewInWindow(50, 50, 800, 600);
//把漫游器加入到场景中
/*PersonWalkManipulator::TravelToScene(viewer.get());*/
//_viewer->addEventHandler(new osgViewer::StatsHandler);
_viewer->addEventHandler(new osgGA::StateSetManipulator(_viewer->getCamera()->getOrCreateStateSet()));
//_viewer->addEventHandler(new osgViewer::ThreadingHandler);
//_viewer->addEventHandler(new osgViewer::LODScaleHandler);
// add a viewport to the viewer and attach the scene graph.
_viewer->setSceneData( root.get() );
osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> _manipulator = new osgGA::KeySwitchMatrixManipulator;
PersonWalkManipulator* pm = new PersonWalkManipulator(_viewer);
osgGA::TerrainManipulator* tm = new osgGA::TerrainManipulator();
_manipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
_manipulator->addMatrixManipulator( '2', "FirstPerson", pm );
_manipulator->addMatrixManipulator( '3', "Flight", new osgGA::FlightManipulator() );
_manipulator->addMatrixManipulator( '4', "Drive", new osgGA::DriveManipulator() );
_manipulator->addMatrixManipulator( '5', "Terrain",tm );
_manipulator->addMatrixManipulator( '6', "Orbit", new osgGA::OrbitManipulator() );
_manipulator->addMatrixManipulator( '7', "FirstPerson", new osgGA::FirstPersonManipulator() );
_manipulator->addMatrixManipulator( '8', "Spherical", new osgGA::SphericalManipulator() );
_viewer->setCameraManipulator( _manipulator.get() );
// create the windows and run the threads.
_viewer->realize();
_viewer->getCamera()->setCullingMode( _viewer->getCamera()->getCullingMode() & ~osg::CullStack::SMALL_FEATURE_CULLING);
return _viewer->run();
}