|
OSG同时按下多个按键后(比如同时按下W和A键),然后松开其中一个按键,则osgGA::MatrixManipulator::handle()将不再产生osgGA::GUIEventAdapter::KEYDOWN事件~于是我考虑使用std::set来存储所有已按下的按键,如下:
case osgGA::GUIEventAdapter::KEYDOWN:
std::set::insert( ea.getKey() );
return true;
case osgGA::GUIEventAdapter::KEYUP:
std::set::erase( ea.getKey() );
return true;
然后,再根据std::set中的值在每一桢中来更新操作器矩阵~于是我又考虑将更新操作放在osgGA::MatrixManipulator::handle()中,但是后来发现osgGA::MatrixManipulator::handle()好象并不是每桢只执行一次,因为当我同时按多个按键的时候摄象机的位置改变明显边快了~于是又考虑是否可以为osgGA::MatrixManipulator设置类似updateCallback这样的节点,发现osgGA::MatrixManipulator只有setNestedCallback()这样的函数,但是我又想用一个比较独立的模块来实现摄象机的操作,请问有什么比较好的方法?
以下是操作器类代码:
#ifndef _CAMERAMANIPULATOR_H_
#define _CAMERAMANIPULATOR_H_
#include <osgGA/MatrixManipulator>
class CameraManipulator : public osgGA::MatrixManipulator {
public:
CameraManipulator();
~CameraManipulator(){};
virtual void setByMatrix( const osg::Matrixd& matrix ){};
virtual void setByInverseMatrix( const osg::Matrixd& matrix ){};
virtual osg::Matrixd getMatrix() const;
virtual osg::Matrixd getInverseMatrix() const;
virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa );
void updatePosition();
private:
osg::Vec3 m_vPosition;
osg::Vec3 m_vRotation;
osg::Vec2 m_vPos;
std::set<int> m_kSet;
float m_fMoveSpeed;
protected:
};
#endif
#include "CameraManipulator.h"
#include <osgViewer/viewer>
CameraManipulator::CameraManipulator() : m_fMoveSpeed( 10.5f ){
m_vPosition = osg::Vec3( 0.0f, 0.0f, 150.0f );
m_vRotation = osg::Vec3( osg:I_2, 0.0f, 0.0f );
m_kSet.clear();
}
osg::Matrixd CameraManipulator::getMatrix() 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 CameraManipulator::getInverseMatrix() 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 CameraManipulator::handle( const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa ){
CameraManipulator::updatePosition();
switch( ea.getEventType() ){
case osgGA::GUIEventAdapter::KEYDOWN:
if( ea.getKey() == 0x20 ){
aa.requestRedraw();
aa.requestContinuousUpdate( false );
return true;
}
m_kSet.insert( ea.getKey() );
return true;
case osgGA::GUIEventAdapter::KEYUP:
m_kSet.erase( ea.getKey() );
return true;
case osgGA::GUIEventAdapter::PUSH:
if( ea.getButton() == 1 ){
m_vPos.set( ea.getX(), ea.getY() );
return true;
}
return false;
case osgGA::GUIEventAdapter:RAG:
m_vRotation._v[2] += osg::DegreesToRadians( ( ea.getX() - m_vPos.x() ) * 0.5 );
m_vRotation._v[0] += osg::DegreesToRadians( ( m_vPos.y() - ea.getY() ) * 0.5 );
return false;
default:
return false;
}
}
void CameraManipulator::updatePosition(){
osg::Vec3f eye, center, up, orient, orient_upright;
CameraManipulator::getInverseMatrix().getLookAt( eye, center, up );
orient.set( ( center - eye ).x() / ( center - eye ).length(),
( center - eye ).y() / ( center - eye ).length(),
( center - eye ).z() / ( center - eye ).length() );
orient.normalize();
orient_upright.set( ( orient ^ up ).x() / ( orient ^ up ).length(),
( orient ^ up ).y() / ( orient ^ up ).length(),
( orient ^ up ).z() / ( orient ^ up ).length() );
orient_upright.normalize();
if( m_kSet.find( 'w' ) != m_kSet.end() ){
m_vPosition += osg::Vec3( m_fMoveSpeed * orient.x(),
m_fMoveSpeed * orient.y(),
m_fMoveSpeed * orient.z() );
}
if( m_kSet.find( 's' ) != m_kSet.end() ){
m_vPosition += osg::Vec3( -m_fMoveSpeed * orient.x(),
-m_fMoveSpeed * orient.y(),
-m_fMoveSpeed * orient.z() );
}
if( m_kSet.find( 'a' ) != m_kSet.end() ){
m_vPosition += osg::Vec3( -m_fMoveSpeed * orient_upright.x(),
-m_fMoveSpeed * orient_upright.y(),
-m_fMoveSpeed * orient_upright.z() );
}
if( m_kSet.find( 'd' ) != m_kSet.end() ){
m_vPosition += osg::Vec3( m_fMoveSpeed * orient_upright.x(),
m_fMoveSpeed * orient_upright.y(),
m_fMoveSpeed * orient_upright.z() );
}
if( m_kSet.find( 'q' ) != m_kSet.end() )
m_vPosition += osg::Vec3( 0.0f, 0.0f, m_fMoveSpeed );
if( m_kSet.find( 'e' ) != m_kSet.end() )
m_vPosition += osg::Vec3( 0.0f, 0.0f, -m_fMoveSpeed );
} |
|