OSG例程(2) 碰撞检测

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(voidconst;
    
virtual osg::Matrix getInverseMatrix(voidconst;

    
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(
voidconst
{
    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(
voidconst
{
    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();

}

  

其中使用到的ceep.ive,随便用max扔俩box什么的,导出即可。
原文地址:https://www.cnblogs.com/mumuliang/p/1884494.html