|
楼主 |
发表于 2013-4-12 08:39:07
|
显示全部楼层
Csouth头文件如下:
/* -*-c++-*- OpenSceneGraph - 2008.6.16 by FreeSouth * * RambleSystem操作器管理类,用来管理操作器 */
//------------------------------//------------------------------
#pragma once
//------------------------------//------------------------------
#include <osgViewer/Viewer>
#include <osgGA/MatrixManipulator>
#include <osgUtil/IntersectVisitor>
#include <osg/LineSegment>
#include <osg/MatrixTransform>
#include <osg/Geometry>
#include <sstream>
#include <osg/ComputeBoundsVisitor>
//------------------------------//------------------------------
class CSouth: public osgGA::MatrixManipulator
{
public:
CSouth(void);
public:
~CSouth(void);
//碰撞检测开启状态查询。
bool m_bPeng;
//得到当前视点位置
osg::Vec3 GetPosition() ;
private:
//结点值,用来测试碰撞检测的
osg::ref_ptr<osg::Node> m_node;
//相机操作器
unsigned int m_nID;
//移动速度
float m_fMoveSpeed;
//位置
osg::Vec3 m_vPosition;
//旋转角度
osg::Vec3 m_vRotation;
//左键是否按下
bool m_bLeftButtonDown;
//左键点下时屏幕坐标
float m_fpushX;
//右键点下时屏幕坐标
float m_fpushY; public:
//碰撞检测是否开启
void setPeng(bool peng) ;
//得到碰撞检测开启状态
bool getPeng() ;
//如果碰撞检测开启则关闭,如果关闭则开启
void setFpeng() ;
//设置要进行碰撞检测的数据
virtual void setNode(osg::Node*);
// 虚函数
virtual void setByMatrix(const osg::Matrixd& matrix);
// 虚函数
virtual void setByInverseMatrix(const osg::Matrixd& matrix);
virtual osg::Matrixd getMatrix(void) const;
// 得到逆矩阵
virtual osg::Matrixd 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 *) ;
//计算家的位置 len为绘制图形左右宽度,单位米
void computeHomePosition(float len,CString type);
//在树结构中使用name查找需要的节点
osg::Node* findNamedNode(const std::string& searchName,osg::Node* currNode);
};
//------------------------------//------------------------------
Csouth.cpp文件服下:
//------------------------------//------------------------------
//By FreeSouth at 2008 6 16 ieysx@163.com www.osgChina.org
#include <stdafx.h >
#include "South.h"
//------------------------------//------------------------------
//设置一些初始值
CSouth::CSouth(void): m_fMoveSpeed(1350.0f)
//左键没有按下
, m_bLeftButtonDown(false)
//左键点下时初始坐标为0
, m_fpushX(0)
//初始角速度是2.5
, m_fAngle(2.5)
//开始时碰撞检测关闭
, m_bPeng(true)
//右键点下时初始坐标也为0
, m_fpushY(0)
{
//出生点为000 ,即视点所在的初始位置
m_vPosition = osg::Vec3(0.0f, -35000.0f,190.0f); //-35000 190
//初始角度
m_vRotation = osg::Vec3(osg:I_2,0,0.0f);//osg::PI_2
}
//------------------------------//------------------------------
//析构函数
CSouth::~CSouth(void) { }
//------------------------------//------------------------------
void CSouth::setByMatrix(const osg::Matrixd & matrix) { }
//------------------------------//------------------------------
void CSouth::setByInverseMatrix(const osg::Matrixd& matrix) { }
//------------------------------//------------------------------
//得到矩阵,这是标准接口,用于控制场景
osg::Matrixd CSouth::getMatrix(void) 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 CSouth::getInverseMatrix(void) 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));
}
//------------------------------//------------------------------
//handle
bool CSouth::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us)
{
//得到x的初始屏幕坐标
float mouseX = ea.getX();
//得到y的初始屏幕坐标
float mouseY = ea.getY();
//判断事件类型
switch(ea.getEventType())
{
//如果是鼠标按下的事件
case(osgGA::GUIEventAdapter::KEYDOWN):
{
//如果是空格
if (ea.getKey() == 0x20)//' '
{
//重绘
us.requestRedraw();
us.requestContinuousUpdate(false);
return true;
}
//如果是home键,则视点向上移动
if (ea.getKey() == 0xFF50)//home
{
ChangePosition(osg::Vec3 (0, 0, m_fMoveSpeed)) ;
return true;
}
//如果是end键,同视点向下移动
if (ea.getKey() == 0xFF57) //end
{
ChangePosition(osg::Vec3 (0, 0, -m_fMoveSpeed)) ;
return true;
}
//如果是加号键则加速
if (ea.getKey() == 0x2B)//+
{
m_fMoveSpeed += 1.0f;
return true;
}
//如果是减号键则减速
if (ea.getKey() == 0x2D)//-
{
m_fMoveSpeed -= 1.0f;
if (m_fMoveSpeed < 1.0f)
{
m_fMoveSpeed = 1.0f;
}
return true;
}
//向前走,W键
if ( ea.getKey () == 0x57 || ea.getKey () == 0x77)//up
{
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;
}
//向后退,S键,或者DOWN键
if (ea.getKey() == 0xFF54 || ea.getKey () == 0x53 || ea.getKey () == 0x73 )//down
{
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;
}
//A left 向左平移
if (ea.getKey () == 0x41||ea.getKey () == 0x61||ea.getKey()== 37)
{
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;
}
//D right 向右平移
if (ea.getKey () == 0x44||ea.getKey () == 0x64||ea.getKey() == 39)
{
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;
}
//Up 向上平移
if (ea.getKey() == 38)
{
ChangePosition(osg::Vec3 (0,0,-m_fMoveSpeed )) ;//* cosf(osg::PI_2+m_vRotation._v[1]
//ChangePosition(osg::Vec3 (0,m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[1]),0)) ;
return true;
}
//Down 向下平移
if (ea.getKey() == 40)
{
ChangePosition(osg::Vec3 (0,0,m_fMoveSpeed )) ;
/*ChangePosition(osg::Vec3 (0,-m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[1]),0)) ;
ChangePosition(osg::Vec3 (-m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[1]),0,0)) ;*/
return true;
}
if (ea.getKey() == 0xFF53)//Right
{
m_vRotation._v[2] -= osg:egreesToRadians(m_fAngle);
/*if(m_node.get())
{
osg::Node* foundNode = NULL;
foundNode = findNamedNode("Axis",m_node);
if (foundNode!=NULL)
{
osg::ref_ptr<osg::Node> temp=new osg::Node();
temp=foundNode;
foundNode->asGroup()->getParent(0)->removeChildren(0,foundNode->asGroup()->getParent(0)->getNumChildren());
osg::ref_ptr<osg::MatrixTransform> pat=new osg::MatrixTransform();
osg::Vec3d delta(-m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]),m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0);
m_vPosition += delta;
pat->setMatrix(osg::Matrix::translate(m_vPosition));
pat->addChild(temp.get());
foundNode->asGroup()->addChild(pat.get());
}
}*/
}
if (ea.getKey()== 0xFF51)//Left
{
m_vRotation._v[2] += osg::DegreesToRadians(m_fAngle);
}
if (ea.getKey() == 0x46 || ea.getKey() == 0x66)//F 返回初始位置
{
computeHomePosition(-35000,"");
m_fAngle -= 0.2 ;
return true ;
}
if (ea.getKey() == 0x47 || ea.getKey() == 0x67)//G
{
m_fAngle += 0.2 ;
return true ;
}
return false;
}
//单击
case (osgGA::GUIEventAdapter ::PUSH ):
//如果是左键,记录下来,因为左键拖动时场景也要转的
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));
//m_vRotation._v[0] += osg::DegreesToRadians(1.1*(mouseY-m_fpushY)) ;
////防止背过去
//if (m_vRotation._v [0] >= 3.14)
//m_vRotation._v [0] = 3.14 ;
//if (m_vRotation._v [0] <= 0)
//m_vRotation._v [0] = 0 ;
}
return false ;
//键弹起
case (osgGA::GUIEventAdapter ::RELEASE ):
if ( ea.getButton () == 1)
{
m_bLeftButtonDown = false ;
}
return false ;
default: return false;
}
}
//在树结构中使用name查找需要的节点
osg::Node* CSouth::findNamedNode(const std::string& searchName,osg::Node* currNode)
{
osg::Group* currGroup;
osg::Node* foundNode;
// 检查输入的节点是否是合法的,
// 如果输入节点为NULL,则直接返回NULL。
if ( !currNode)
{
return NULL;
}
// 如果输入节点合法,那么先检查该节点是否就是我们想要的结果。
// 如果确为所求,那么直接返回输入节点。
if (currNode->getName() == searchName)
{
return currNode;
}
// 如果输入节点并非所求,那么检查它的子节点(不包括叶节点)情况。
// 如果子节点存在,则使用递归调用来检查每个子节点。
// 如果某一次递归的返回值非空,说明已经找到所求的节点,返回其指针。
// 如果所有的节点都已经遍历过,那么说明不存在所求节点,返回NULL。
currGroup = currNode->asGroup(); // returns NULL if not a group.
if ( currGroup )
{
for (unsigned int i = 0 ; i <currGroup->getNumChildren(); i ++)
{
foundNode = findNamedNode(searchName,currGroup->getChild(i));
if (foundNode)
return foundNode; // 找到所求节点。
}
return NULL; // 遍历结束,不存在所求节点。
}
else
{
return NULL; // 该节点不是组节点,返回NULL
}
}
//------------------------------//------------------------------
//改变位置
void CSouth::ChangePosition(osg::Vec3 &delta)
{
if (m_bPeng)
{
//看新值与旧值之间的连线是否与模型有交点!如果要到达的位置与现在的位置有交点的话,如果碰撞检测也开启了,就不移动。
osg::Vec3 newPos = m_vPosition + delta;
osgUtil::IntersectVisitor iv;
//前后的线段
osg::ref_ptr<osg:ineSegment> 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()) ;
//接受碰撞的检测node
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 ;
}
//------------------------------//------------------------------
//计算家的位置,其实是包围盒的中心处 len为绘制图形左右宽度,单位米
void CSouth::computeHomePosition(float len,CString type)
{
//如果有模型,则计算包围球的球心
if(m_node.get())
{
osg::BoundingBox bb;
osg::ComputeBoundsVisitor cbv;
osg::Vec3 posBQ(0,0,0);
m_node->dirtyBound();
m_node->accept(cbv);
bb=cbv.getBoundingBox();
posBQ.x()=bb.xMax()-(bb.xMax()-bb.xMin())/2;
posBQ.z()=bb.zMax()-(bb.zMax()-bb.zMin())/2;
float x,z;
x=bb.xMax()-bb.xMin();
z=bb.zMax()-bb.zMin();
if(x>z)
posBQ.y()=-x*2+2*x/11;
else
posBQ.y()=-z*2+2*z/11;
/*if(type=="空心板")
posBQ.y()+=1700;
if(type=="空心板桥面")
posBQ.y()+=8000;
if(type=="盖梁柱式墩盖梁")
posBQ.y()+=5000;
if(type.Left(8)=="轻型桥台")
posBQ.y()+=7000;*/
SetPosition(posBQ);
}
////空心板的初始视点位置
//if(m_node.get())
//{
// osg::Vec3 bp(0,-35000,50);
// SetPosition(bp) ;
//}
}
//------------------------------//------------------------------
//设置碰撞检测为开启或者关闭
void CSouth::setPeng(bool peng)
{
m_bPeng = peng ;
}
//------------------------------//------------------------------
//得到碰撞检测的状态
bool CSouth::getPeng()
{
return m_bPeng ;
}
//------------------------------//------------------------------
//如果碰撞测试在开启,则关闭它,如果在关闭,则开启它
void CSouth::setFpeng()
{
m_bPeng = !m_bPeng ;
}
//------------------------------//------------------------------
|
|