|
大家好!小弟编写了一个相机跟随船舶demo,按下运动键后物体运动方向与相机运动方向垂直,折腾了一天还是无法解决,恳请各位帮忙,谢谢!以下为源码:
class boatDeviceStateType//该类用于指示船舶运动状态
{
public:
boatDeviceStateType():
moveFwdOrBack(0),
moveTurnLeftOrRight(0),
m_fSpeed(0.50f),
bStartFollowShip(false),
m_fAngle(0.50f),
_matBoat(osg::Matrixd::identity())
{
}
~boatDeviceStateType(void);
public:
/**前进或后退标志:
0: 停止
1: 前进
-1:后退
*/
int moveFwdOrBack;
/**左转弯或右转弯标志
0: 未转弯状态
1: 左转弯
-1:右转弯
*/
int moveTurnLeftOrRight;
/**
速度参数,相机运行及船舶运行需要用到
初始速度设为2.0
*/
float m_fSpeed;
/**
单位相机旋转角度,初始设置为2.0
*/
float m_fAngle;
/**
是否开启相机绑定,默认关闭
*/
bool bStartFollowShip;
osg::Matrixd _matBoat;
};
class boatGUIEvent :
public osgGA::GUIEventHandler
{
public:
boatGUIEvent(boatDeviceStateType* tids)
{
boatInputDeviceState=tids;
}
~boatGUIEvent(void);
virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
{
switch(ea.getEventType())
{
case osgGA::GUIEventAdapter::KEYDOWN:
{
if (ea.getKey()==0xFF52)//前行
{
boatInputDeviceState->moveFwdOrBack=1;
//std::cout<<"GUI:"<<std::endl;
}
else if (ea.getKey()==0xFF54)//后退
{
boatInputDeviceState->moveFwdOrBack=-1;
}
if (ea.getKey()==0xFF53)//右转弯
{
boatInputDeviceState->moveTurnLeftOrRight=-1;
}
else if(ea.getKey()==0xFF51)//左转弯
{
boatInputDeviceState->moveTurnLeftOrRight=1;
}
if (ea.getKey()==0xFFAB)//按下加号键,对应于KEY_KP_Add
{
boatInputDeviceState->m_fSpeed+=0.001;
}
else if(ea.getKey()==0xFFAD)//按下减号键,对应 KEY_UP_Subtract
{
boatInputDeviceState->m_fSpeed-=0.001;
if(boatInputDeviceState->m_fSpeed<=0.001)
boatInputDeviceState->m_fSpeed=0.001;
}
return false;
break;
}
case osgGA::GUIEventAdapter::KEYUP:
{
boatInputDeviceState->moveFwdOrBack=0;//停止前进及后退
boatInputDeviceState->moveTurnLeftOrRight=0;
return false;
break;
}
default:
return false;
break;
}
protected:
/**外设接收标志*/
boatDeviceStateType* boatInputDeviceState;
};
//
struct updateAccumulatoredMatrix:public osg::NodeCallback
{
virtual void operator()(osg::Node* node,osg::NodeVisitor* nv)
{
_matrix=osg::computeWorldToLocal(nv->getNodePath());
traverse(node,nv);
}
osg::Matrix _matrix;
};
struct transformAccumulator
{
public:
transformAccumulator()
{
_parent=NULL;
node=new osg::Node;
mpcb=new updateAccumulatoredMatrix;
node->setUpdateCallback(mpcb);
}
bool attachToGroup(osg::Group* g)
{
bool _success=false;
if (_parent!=NULL)
{
int n=_parent->getNumChildren();
for (int i=0;i<n;i++)
{
if (node==_parent->getChild(i))
{
_parent->removeChild(i,1);
_success=true;
}
}
if (!_success)
{
return _success;
}
}
g->addChild(node);
return true;
}
osg::Matrix getMatrix()
{
return mpcb->_matrix;
}
protected:
osg::ref_ptr<osg::Group> _parent;
osg::Node* node;
updateAccumulatoredMatrix* mpcb;
};
class followNodeMatrixManipulator:
public osgGA::CameraManipulator
{
public:
followNodeMatrixManipulator(transformAccumulator* ta)
{
worldCoordinatesOfNode=ta;
theMatrix=osg::Matrixd::identity();
}
//~followNodeMatrixManipulator();
virtual void setByMatrix(const osg::Matrixd& matrix)
{
theMatrix=matrix;
}
virtual void setByInverseMatrix(const osg::Matrixd& matrix)
{
theMatrix=osg::Matrix::inverse(matrix);
}
virtual osg::Matrixd getMatrix() const
{
return theMatrix;
}
virtual osg::Matrixd getInverseMatrix() const
{
//将矩阵从Y轴向上旋转到Z轴向上
osg::Matrixd _mat;
_mat=theMatrix* osg::Matrixd::rotate(-osg:I_2,osg::Vec3(1.0,0,0));
return _mat;
}
void updateTheMatrix()
{
theMatrix=worldCoordinatesOfNode->getMatrix();
}
bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
{
switch(ea.getEventType())
{
case (osgGA::GUIEventAdapter::FRAME):
{
updateTheMatrix();
return false;
}
}
return false;
}
protected:
transformAccumulator* worldCoordinatesOfNode;
osg::Matrixd theMatrix;
};
/**
加载天空球纹理
*/
osg::ref_ptr<osg::TextureCubeMap> loadCubeMapTexture()
{
osg::ref_ptr<osg::TextureCubeMap> cubeMap=new osg::TextureCubeMap;
cubeMap->setInternalFormat(GL_RGBA);
cubeMap->setFilter(osg::Texture::MIN_FILTER,osg::Texture:INEAR_MIPMAP_LINEAR);
cubeMap->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
cubeMap->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
cubeMap->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_X,
osgDB::readImageFile("resources/textures/sky_fair_cloudy/west.png"));
cubeMap->setImage(osg::TextureCubeMap::POSITIVE_X,
osgDB::readImageFile("resources/textures/sky_fair_cloudy/east.png"));
cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_Y,
osgDB::readImageFile("resources/textures/sky_fair_cloudy/up.png"));
cubeMap->setImage(osg::TextureCubeMap::POSITIVE_Y,
osgDB::readImageFile("resources/textures/sky_fair_cloudy/down.png"));
cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_Z,
osgDB::readImageFile("resources/textures/sky_fair_cloudy/south.png"));
cubeMap->setImage(osg::TextureCubeMap::POSITIVE_Z,
osgDB::readImageFile("resources/textures/sky_fair_cloudy/north.png"));
return cubeMap;
}
//船舶运动回调
class BoatPcsitionCallback:public osg::NodeCallback
{
public:
BoatPcsitionCallback(osgOcean::OceanScene *oceanScene,boatDeviceStateType* boatDevState)
{
_oceanScene=oceanScene;
boatInputDeviceSta=boatDevState;
m_fMoveSpeed=0.8;
m_Angle=2.0;
}
virtual void operator()(osg::Node* node,osg::NodeVisitor * nv)
{
if (nv->getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
{
osg::MatrixTransform* mt=dynamic_cast<osg::MatrixTransform*>(node);
if (!mt ||! _oceanScene) return;
osg::Matrix mat=osg::computeLocalToWorld(nv->getNodePath());
osg::Vec3d pos=mat.getTrans();
osg::Vec3f normal;
float height=_oceanScene->getOceanSurfaceHeightAt(pos.x(),pos.y(),&normal);
float m_x=0.0;
float m_y=0.0;
static float m_Turn=0.0000;
if (boatInputDeviceSta->moveFwdOrBack==1)//前进
{
m_x=fabs(boatInputDeviceSta->m_fSpeed)*cosf(m_Turn);
m_y=fabs(boatInputDeviceSta->m_fSpeed)*sinf(m_Turn);
}
else if (boatInputDeviceSta->moveFwdOrBack==-1)//后退
{
m_x=-fabs(boatInputDeviceSta->m_fSpeed)*cosf(m_Turn);
m_y=-fabs(boatInputDeviceSta->m_fSpeed)*sinf(m_Turn);
}
else if (boatInputDeviceSta->moveFwdOrBack==0)//停止前进
{
m_x=0.0;
m_y=0.0;
}
if (boatInputDeviceSta->moveTurnLeftOrRight==1)//左转弯
{
m_Turn+=osg:egreesToRadians(m_Angle);
}
else if (boatInputDeviceSta->moveTurnLeftOrRight==-1)//右转弯
{
m_Turn-=osg::DegreesToRadians(m_Angle);
}
else if(boatInputDeviceSta->moveTurnLeftOrRight==0)//停止转弯
{
}
//mat.makeTranslate(osg::Vec3f(pos.x()+m_x,pos.y()+m_y,height-0.20));
mat.makeTranslate(osg::Vec3f(pos.x()+m_x,pos.y()+m_y,height+10));
osg::Matrix rot;
rot.makeIdentity();
rot.makeRotate(normal.x()/5,osg::Vec3f(1.0f,0.0f,0.0f),normal.y()/5,osg::Vec3f(0.0f,1.0f,0.0f),
m_Turn,osg::Vec3f(0.0f,0.0f,1.0f));
//a+=0.005;
mat=rot*mat;
mat=mat;
boatInputDeviceSta->_matBoat=mat;
mt->setMatrix(mat);
}
traverse(node, nv);
}
private:
osgOcean::OceanScene *_oceanScene;
boatDeviceStateType* boatInputDeviceSta;
};
int main()
{
osg::ref_ptr<osgViewer::Viewer> viewer=new osgViewer::Viewer;
viewer->setUpViewInWindow(150,150,1024,768,0);
//添加海洋
osg::ref_ptr<osgOcean::FFTOceanSurface> oceanSurface=new osgOcean::FFTOceanSurface(64,
256,100,osg::Vec2f(1.1f,1.1f),12.0f,1000.0f,0.8,1e-9,true,2.5,10.0f,256);//1e-8为浪高参数
osg::ref_ptr<osgOcean::OceanScene> oceanScene=new osgOcean::OceanScene(oceanSurface.get());
//添加海面数据
viewer->addEventHandler(oceanSurface->getEventHandler());
viewer->addEventHandler(oceanScene->getEventHandler());
//添加天空盒
osg::ref_ptr<osg::TextureCubeMap> cubemap=loadCubeMapTexture();
osg::ref_ptr<SkyDome> skyDome=new SkyDome(10000.0f,16,16,cubemap.get());//new SkyDome(1900.0f,16,16,cubemap.get());
skyDome->setNodeMask(oceanScene->getReflectedSceneMask() |oceanScene->getNormalSceneMask());
osg::MatrixTransform * transform=new osg::MatrixTransform;
transform->setDataVariance(osg::Object::DYNAMIC);
transform->setMatrix(osg::Matrix::translate(osg::Vec3(0.0,0.0,0.0)));
transform->setCullCallback(new SkyCameraTrackCallback);
transform->addChild(skyDome);
oceanScene->addChild(transform);
//设置雾效与反射
oceanScene->setAboveWaterFog(0.0012,osg::Vec4f(0.67,0.87,0.93,1.0));
oceanScene->enableReflections(true);
oceanSurface->setEnvironmentMap(cubemap);
//水花
oceanSurface->setFoamBottomHeight(2.20);
oceanSurface->setFoamTopHeight(3.0);
oceanSurface->enableCrestFoam(true);
//
boatDeviceStateType* bDeviceState=new boatDeviceStateType;
boatGUIEvent* myBoatGUIEvent=new boatGUIEvent(bDeviceState);
viewer->addEventHandler(myBoatGUIEvent);
//
//添加小船
osg::ref_ptr<osg::Node> galley=osgDB::readNodeFile("resources/boat/boat.osgb");
galley->setNodeMask(oceanScene->getReflectedSceneMask() |oceanScene->getNormalSceneMask()
|oceanScene->getRefractedSceneMask());
osg::ref_ptr<osg::MatrixTransform>galleyMat=new osg::MatrixTransform;
/*osg::Matrix rot1;
rot1.makeIdentity();
rot1.makeRotate(0.0,osg::Vec3f(1.0f,0.0f,0.0f),0.0,osg::Vec3f(0.0f,1.0f,0.0f),
osg::DegreesToRadians(90.0),osg::Vec3f(0.0f,0.0f,1.0f));*/
galleyMat->setMatrix(/*rot1**/osg::Matrix::translate(osg::Vec3f(50.0f,0.0f,0.0f)));
galleyMat->setUpdateCallback(new BoatPcsitionCallback(oceanScene,bDeviceState));
galleyMat->addChild(galley);
oceanScene->addChild(galleyMat);
osg::ref_ptr<osg::Group> group=new osg::Group;
//
transformAccumulator* BoatTrackl=new transformAccumulator();//
BoatTrackl->attachToGroup(galleyMat);//绑定跟随船
followNodeMatrixManipulator* tb=new followNodeMatrixManipulator(BoatTrackl);//添加船舶跟随操作器
viewer->setCameraManipulator(tb);
group->addChild(oceanScene);
osgUtil::Optimizer optimizer;
optimizer.optimize(oceanScene.get());
optimizer.optimize(oceanSurface.get());
optimizer.optimize(galleyMat.get());
optimizer.reset();
//osgGA::TrackballManipulator *tb=new osgGA::TrackballManipulator;//添加操作器
////tb->setHomePosition(osg::Vec3f(0.0,0.0,20.0f),osg::Vec3f(0.0,20.0f,0.0),osg::Vec3f(0.0,0.0,1.0f));
//tb->setHomePosition(osg::Vec3f(0.0,0.0,20.0f),osg::Vec3f(20.0,0.0f,0.0),osg::Vec3f(0.0,0.0,1.0f));
//viewer->setCameraManipulator(tb);
osg::DisplaySettings* ds=osg::DisplaySettings::instance();
ds->setNumMultiSamples(16);
viewer->setDisplaySettings(ds);
viewer->setSceneData(group.get());
viewer->run();
return 0;
}
在此表示感谢! |
|