OSG程序设计教程,第六章漫游,矩阵操作器。
CSouth.cpp稍有不同:
1.将判断keydown值的多个if换成了switch。
2.button拖动的旋转增量*0.001
3.RIGHT/LEFT key的旋转增量*0.1
CSouth.h
/************************************************************************/
/* Management Class of Manipulator */
/************************************************************************/
#pragma once
#include <osgViewer/Viewer>
#include <osgGA/MatrixManipulator>
#include <osgUtil/IntersectVisitor>
#include <osg/LineSegment>
class CSouth:public osgGA::MatrixManipulator
{
public:
CSouth();
~CSouth();
private:
osg::ref_ptr<osg::Node> m_node; // node for detect collide
unsigned int m_nID; // camera operator
float m_fMoveSpeed; // move speed
osg::Vec3 m_vPosition; // position
osg::Vec3 m_vRotation; // rotation;
bool m_bleftButtonDown; // if the left btn is down
float m_fpushX; // x when left btn was down
float m_fpushY; // y ....
bool m_bCollide; // switch for detect collide
public:
void setCollide(bool collide);
bool getCollide();
void setFcollide();
virtual void setNode(osg::Node*);
virtual void setByMatrix(const osg::Matrix &matrix);
virtual void setByInverseMatrix(const osg::Matrix &matrix);
virtual osg::Matrix getMatrix(void) const;
virtual osg::Matrix getInverseMatrix(void) const;
virtual bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us);
float m_fAngle;
void ChangePosition(osg::Vec3 &delta);
float getSpeed();
void setSpeed(float);
void SetPosition(osg::Vec3 &position);
void SetPosition(double * );
osg::Vec3 GetPosition();
void computeHomePosition();
};
/* Management Class of Manipulator */
/************************************************************************/
#pragma once
#include <osgViewer/Viewer>
#include <osgGA/MatrixManipulator>
#include <osgUtil/IntersectVisitor>
#include <osg/LineSegment>
class CSouth:public osgGA::MatrixManipulator
{
public:
CSouth();
~CSouth();
private:
osg::ref_ptr<osg::Node> m_node; // node for detect collide
unsigned int m_nID; // camera operator
float m_fMoveSpeed; // move speed
osg::Vec3 m_vPosition; // position
osg::Vec3 m_vRotation; // rotation;
bool m_bleftButtonDown; // if the left btn is down
float m_fpushX; // x when left btn was down
float m_fpushY; // y ....
bool m_bCollide; // switch for detect collide
public:
void setCollide(bool collide);
bool getCollide();
void setFcollide();
virtual void setNode(osg::Node*);
virtual void setByMatrix(const osg::Matrix &matrix);
virtual void setByInverseMatrix(const osg::Matrix &matrix);
virtual osg::Matrix getMatrix(void) const;
virtual osg::Matrix getInverseMatrix(void) const;
virtual bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us);
float m_fAngle;
void ChangePosition(osg::Vec3 &delta);
float getSpeed();
void setSpeed(float);
void SetPosition(osg::Vec3 &position);
void SetPosition(double * );
osg::Vec3 GetPosition();
void computeHomePosition();
};
CSouth.cpp
/************************************************************************/
/* Management Class of Manipulator */
/************************************************************************/
#include "CSouth.h"
// constructor func
CSouth::CSouth(void):m_fMoveSpeed(1.5f)
,m_bleftButtonDown(false)
,m_fpushX(0)
,m_fpushY(0)
,m_fAngle(2.5)
,m_bCollide(false)
{
m_vPosition = osg::Vec3(0.0f,0.0f,5.0f);
m_vRotation = osg::Vec3(osg::PI_2,0.0f,0.0f);
}
// destructor
CSouth::~CSouth(void)
{
}
void CSouth::setByMatrix(const osg::Matrix &matrix)
{}
void CSouth::setByInverseMatrix(const osg::Matrix &matrix)
{}
osg::Matrix CSouth::getMatrix(void) const
{
osg::Matrix 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::Matrix CSouth::getInverseMatrix(void) const
{
osg::Matrix 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 CSouth::handle(const osgGA::GUIEventAdapter &ea
, osgGA::GUIActionAdapter &us)
{
float mouseX = ea.getX();
float mouseY = ea.getY();
switch (ea.getEventType())
{
// keydown event
case (osgGA::GUIEventAdapter::KEYDOWN):
{
switch (ea.getKey())
{
case (0x20): // SPACE
// redraw
us.requestRedraw();
us.requestContinuousUpdate(false);
return true;
case (0xFF50): // HOME
ChangePosition(osg::Vec3(0,0,m_fMoveSpeed));
return true;
case (0xFF57): // END
ChangePosition(osg::Vec3(0,0,-m_fMoveSpeed));
return true;
case (0x2B): // +
m_fMoveSpeed += 1.0f;
return true;
case (0x50): // -
m_fMoveSpeed -= 1.0f;
if (m_fMoveSpeed < 1.0f)
{
m_fMoveSpeed = 1.0f;
}
return true;
case (0xFF52): // UP
case (0x57): // W
case (0x77): // w
ChangePosition( osg::Vec3(0 , m_fMoveSpeed*sinf(osg::PI_2 + m_vRotation._v[2]) , 0 ) );
ChangePosition( osg::Vec3( m_fMoveSpeed*cosf(osg::PI_2 + m_vRotation._v[2]), 0 , 0 ) );
return true;
case (0xFF54): // DOWN
case (0x53): // S
case (0x73): // s
ChangePosition( osg::Vec3(0 , -m_fMoveSpeed*sinf(osg::PI_2 + m_vRotation._v[2]) , 0 ) );
ChangePosition( osg::Vec3( -m_fMoveSpeed*cosf(osg::PI_2 + m_vRotation._v[2]), 0 , 0 ) );
return true;
case (0x61): // a
case (0x41): // A
ChangePosition( osg::Vec3(0 , m_fMoveSpeed*cosf(osg::PI_2 + m_vRotation._v[2]) , 0 ) );
ChangePosition( osg::Vec3( -m_fMoveSpeed*sinf(osg::PI_2 + m_vRotation._v[2]), 0 , 0 ) );
return true;
case (0x64): // d
case (0x44): // D
ChangePosition( osg::Vec3(0 , -m_fMoveSpeed*cosf(osg::PI_2 + m_vRotation._v[2]) , 0 ) );
ChangePosition( osg::Vec3( m_fMoveSpeed*sinf(osg::PI_2 + m_vRotation._v[2]), 0 , 0 ) );
return true;
case (0xFF53): // ->RIGHT
m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle*0.1);
return true;
case (0xFF51): // <-LEFT
m_vRotation._v[2] += osg::DegreesToRadians(m_fAngle*0.1);
return true;
case (0x66): // f
case (0x46): // F
computeHomePosition();
m_fAngle -=0.2;
return true;
case (0x67): // g
case (0x47): // G
m_fAngle +=0.2;
return true;
default:
return false;
}
}
case (osgGA::GUIEventAdapter::PUSH):
// left button
if (ea.getButton() == 1)
{
m_fpushX = mouseX;
m_fpushY = mouseY;
m_bleftButtonDown = true;
}
return false;
case (osgGA::GUIEventAdapter::DRAG):
if (m_bleftButtonDown)
{
m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle * (mouseX - m_fpushX)* 0.001);
m_vRotation._v[0] += osg::DegreesToRadians(1.1 * (mouseY - m_fpushY)* 0.001);
if (m_vPosition._v[0] >=3.14)
m_vPosition._v[0] = 3.14;
if (m_vPosition._v[0] <= 0)
m_vPosition._v[0] = 0;
}
return false;
case (osgGA::GUIEventAdapter::RELEASE):
// left button
if (ea.getButton()==1)
{
m_bleftButtonDown = false;
}
return false;
default:
return false;
}
}
void CSouth::ChangePosition(osg::Vec3 &delta)
{
if (m_bCollide)
{
osg::Vec3 newPos = m_vPosition + delta;
osgUtil::IntersectVisitor iv;
osg::ref_ptr<osg::LineSegment> line = new osg::LineSegment(newPos, m_vPosition);
osg::ref_ptr<osg::LineSegment> lineZ = new osg::LineSegment(newPos + osg::Vec3(0.0f,0.0f, m_fMoveSpeed),
newPos - osg::Vec3(0.0f,0.0f, m_fMoveSpeed));
iv.addLineSegment(lineZ.get());
iv.addLineSegment(line.get());
m_node->accept(iv);
if (!iv.hits())
{
m_vPosition += delta;
}
}
else
m_vPosition += delta;
}
float CSouth::getSpeed()
{
return m_fMoveSpeed;
}
void CSouth::setSpeed(float sp)
{
m_fMoveSpeed = sp;
}
void CSouth::SetPosition(osg::Vec3 &position)
{
m_vPosition = position;
}
void CSouth::SetPosition(double * position)
{
m_vPosition._v[0] = position[0];
m_vPosition._v[1] = position[1];
m_vPosition._v[2] = position[2];
}
osg::Vec3 CSouth::GetPosition()
{
return m_vPosition;
}
void CSouth::setNode(osg::Node * node)
{
m_node = node;
}
void CSouth::computeHomePosition()
{
if (m_node.get())
{
const osg::BoundingSphere &boudingSphere = m_node -> getBound();
osg::Vec3 bp = boudingSphere._center;
SetPosition(bp);
}
}
void CSouth::setCollide(bool collide)
{
m_bCollide = collide;
}
bool CSouth::getCollide()
{
return m_bCollide;
}
void CSouth::setFcollide()
{
m_bCollide = !m_bCollide;
}
/* Management Class of Manipulator */
/************************************************************************/
#include "CSouth.h"
// constructor func
CSouth::CSouth(void):m_fMoveSpeed(1.5f)
,m_bleftButtonDown(false)
,m_fpushX(0)
,m_fpushY(0)
,m_fAngle(2.5)
,m_bCollide(false)
{
m_vPosition = osg::Vec3(0.0f,0.0f,5.0f);
m_vRotation = osg::Vec3(osg::PI_2,0.0f,0.0f);
}
// destructor
CSouth::~CSouth(void)
{
}
void CSouth::setByMatrix(const osg::Matrix &matrix)
{}
void CSouth::setByInverseMatrix(const osg::Matrix &matrix)
{}
osg::Matrix CSouth::getMatrix(void) const
{
osg::Matrix 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::Matrix CSouth::getInverseMatrix(void) const
{
osg::Matrix 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 CSouth::handle(const osgGA::GUIEventAdapter &ea
, osgGA::GUIActionAdapter &us)
{
float mouseX = ea.getX();
float mouseY = ea.getY();
switch (ea.getEventType())
{
// keydown event
case (osgGA::GUIEventAdapter::KEYDOWN):
{
switch (ea.getKey())
{
case (0x20): // SPACE
// redraw
us.requestRedraw();
us.requestContinuousUpdate(false);
return true;
case (0xFF50): // HOME
ChangePosition(osg::Vec3(0,0,m_fMoveSpeed));
return true;
case (0xFF57): // END
ChangePosition(osg::Vec3(0,0,-m_fMoveSpeed));
return true;
case (0x2B): // +
m_fMoveSpeed += 1.0f;
return true;
case (0x50): // -
m_fMoveSpeed -= 1.0f;
if (m_fMoveSpeed < 1.0f)
{
m_fMoveSpeed = 1.0f;
}
return true;
case (0xFF52): // UP
case (0x57): // W
case (0x77): // w
ChangePosition( osg::Vec3(0 , m_fMoveSpeed*sinf(osg::PI_2 + m_vRotation._v[2]) , 0 ) );
ChangePosition( osg::Vec3( m_fMoveSpeed*cosf(osg::PI_2 + m_vRotation._v[2]), 0 , 0 ) );
return true;
case (0xFF54): // DOWN
case (0x53): // S
case (0x73): // s
ChangePosition( osg::Vec3(0 , -m_fMoveSpeed*sinf(osg::PI_2 + m_vRotation._v[2]) , 0 ) );
ChangePosition( osg::Vec3( -m_fMoveSpeed*cosf(osg::PI_2 + m_vRotation._v[2]), 0 , 0 ) );
return true;
case (0x61): // a
case (0x41): // A
ChangePosition( osg::Vec3(0 , m_fMoveSpeed*cosf(osg::PI_2 + m_vRotation._v[2]) , 0 ) );
ChangePosition( osg::Vec3( -m_fMoveSpeed*sinf(osg::PI_2 + m_vRotation._v[2]), 0 , 0 ) );
return true;
case (0x64): // d
case (0x44): // D
ChangePosition( osg::Vec3(0 , -m_fMoveSpeed*cosf(osg::PI_2 + m_vRotation._v[2]) , 0 ) );
ChangePosition( osg::Vec3( m_fMoveSpeed*sinf(osg::PI_2 + m_vRotation._v[2]), 0 , 0 ) );
return true;
case (0xFF53): // ->RIGHT
m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle*0.1);
return true;
case (0xFF51): // <-LEFT
m_vRotation._v[2] += osg::DegreesToRadians(m_fAngle*0.1);
return true;
case (0x66): // f
case (0x46): // F
computeHomePosition();
m_fAngle -=0.2;
return true;
case (0x67): // g
case (0x47): // G
m_fAngle +=0.2;
return true;
default:
return false;
}
}
case (osgGA::GUIEventAdapter::PUSH):
// left button
if (ea.getButton() == 1)
{
m_fpushX = mouseX;
m_fpushY = mouseY;
m_bleftButtonDown = true;
}
return false;
case (osgGA::GUIEventAdapter::DRAG):
if (m_bleftButtonDown)
{
m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle * (mouseX - m_fpushX)* 0.001);
m_vRotation._v[0] += osg::DegreesToRadians(1.1 * (mouseY - m_fpushY)* 0.001);
if (m_vPosition._v[0] >=3.14)
m_vPosition._v[0] = 3.14;
if (m_vPosition._v[0] <= 0)
m_vPosition._v[0] = 0;
}
return false;
case (osgGA::GUIEventAdapter::RELEASE):
// left button
if (ea.getButton()==1)
{
m_bleftButtonDown = false;
}
return false;
default:
return false;
}
}
void CSouth::ChangePosition(osg::Vec3 &delta)
{
if (m_bCollide)
{
osg::Vec3 newPos = m_vPosition + delta;
osgUtil::IntersectVisitor iv;
osg::ref_ptr<osg::LineSegment> line = new osg::LineSegment(newPos, m_vPosition);
osg::ref_ptr<osg::LineSegment> lineZ = new osg::LineSegment(newPos + osg::Vec3(0.0f,0.0f, m_fMoveSpeed),
newPos - osg::Vec3(0.0f,0.0f, m_fMoveSpeed));
iv.addLineSegment(lineZ.get());
iv.addLineSegment(line.get());
m_node->accept(iv);
if (!iv.hits())
{
m_vPosition += delta;
}
}
else
m_vPosition += delta;
}
float CSouth::getSpeed()
{
return m_fMoveSpeed;
}
void CSouth::setSpeed(float sp)
{
m_fMoveSpeed = sp;
}
void CSouth::SetPosition(osg::Vec3 &position)
{
m_vPosition = position;
}
void CSouth::SetPosition(double * position)
{
m_vPosition._v[0] = position[0];
m_vPosition._v[1] = position[1];
m_vPosition._v[2] = position[2];
}
osg::Vec3 CSouth::GetPosition()
{
return m_vPosition;
}
void CSouth::setNode(osg::Node * node)
{
m_node = node;
}
void CSouth::computeHomePosition()
{
if (m_node.get())
{
const osg::BoundingSphere &boudingSphere = m_node -> getBound();
osg::Vec3 bp = boudingSphere._center;
SetPosition(bp);
}
}
void CSouth::setCollide(bool collide)
{
m_bCollide = collide;
}
bool CSouth::getCollide()
{
return m_bCollide;
}
void CSouth::setFcollide()
{
m_bCollide = !m_bCollide;
}
main.cpp
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
#include "CSouth.h"
int main()
{
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
viewer->setSceneData(osgDB::readNodeFile("..\\ceep.ive"));
viewer->setCameraManipulator(new CSouth());
viewer->realize();
viewer->run();
}
#include <osgViewer/Viewer>
#include <osg/Node>
#include "CSouth.h"
int main()
{
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
viewer->setSceneData(osgDB::readNodeFile("..\\ceep.ive"));
viewer->setCameraManipulator(new CSouth());
viewer->realize();
viewer->run();
}
其中使用到的ceep.ive,随便用max扔俩box什么的,导出即可。