查看: 2185|回复: 3

OSG同时按下多个按键的问题

[复制链接]

该用户从未签到

发表于 2010-1-30 13:38:37 | 显示全部楼层 |阅读模式
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 );
}

该用户从未签到

 楼主| 发表于 2010-1-30 14:10:51 | 显示全部楼层
看了下TrackballManipulator发现它的抛出动作是用的GUIEventAdapter::FRAME
但是现在还是有个问题,同时按两个按键还是会加速~可能是updatePosition()里的问题咯~

该用户从未签到

 楼主| 发表于 2010-1-30 19:44:23 | 显示全部楼层
哈~终于搞定了!
这个相机操作器就和CS、魔兽世界等3D网络游戏的摄象机的操作比较类似了~
WASD控制前后左右移动~
鼠标拖拽控制镜头旋转~
等等~

该用户从未签到

发表于 2010-2-1 13:43:34 | 显示全部楼层
恭喜~~~觉得osg自带的几个操作器挺好用的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表