OSG实例(模型遍历,模型控制,粒子系统,碰撞检测)

OSG建立场景时,一般包含以下步骤:
1,建立模型根节点以及场景类;
2,加入模型;
3,加入模型场景;
4,建立摄像操作,加入场景类;
5,建立模型控制类,加入模型根节点;
6,运行场景。
如下的主函数包含所有的步骤:
其中MyOSGCamera为摄像机控制类;CMyNodeCallback为模型控制类;CMyHelpHandler为帮助显示类
MyOSGCamera控制摄像机的移动方向;
CMyNodeCallback控制模型的前后左右移动;
CMyHelpHandler按 H 键弹出帮助提示。
相关功能比较简单,感兴趣可以看看。

#include "Include.h"
#include "MyOSGCamera.h"
#include "MyNodeCallback.h"
#include "MyHelpHandler.h"
int main(int* argc,char **argv)
{
	osg::ref_ptr<osgViewer::Viewer> myviewer = new osgViewer::Viewer;
	
	//加载模型
	osg::ref_ptr<osg::Group> myroot = new osg::Group;
	myroot->setName("root");

	osg::ref_ptr<osg::Node> mycarNode = osgDB::readNodeFile("myCar.ive");
	osg::ref_ptr<osg::Node> mySceneNode = osgDB::readNodeFile("MyScene.ive");
	myroot->addChild(osgDB::readNodeFile("SkyBox.ive"));
	
	//控制位置Car
	osg::Vec3 vp1 = osg::Vec3(-60.0, -800.0, 0.0);
	osg::Vec3 vp2 = osg::Vec3(0.1, 0.1, 0.1);
	osg::ref_ptr<osg::PositionAttitudeTransform> chposCar = new osg::PositionAttitudeTransform;
	chposCar->addChild(mycarNode);
	chposCar->setPosition(vp1);
	osg::Quat quat(osg::DegreesToRadians(-90.0), osg::Z_AXIS);
	chposCar->setAttitude(quat);
	chposCar->setScale(vp2);
	//设置名字,用于遍历
	chposCar->setName(gMyCarStr);
	myroot->addChild(chposCar);

	//控制位置场景
	osg::ref_ptr<osg::PositionAttitudeTransform> chposScene = new osg::PositionAttitudeTransform;
	chposScene->addChild(mySceneNode);
	chposScene->setScale(osg::Vec3f(100.0, 100.0, 100.0));
	osg::BoundingSphere bs = chposScene->getBound();
	chposScene->setPosition(osg::Vec3(0-bs.center().x(), 0-bs.center().y(), 0-bs.center().z()));
	chposScene->setName(gMySceneStr);
	myroot->addChild(chposScene);
	
	//光源
	osg::ref_ptr<osg::Light> myLight1 = new osg::Light;
	myLight1->setLightNum(0);
	myLight1->setPosition(osg::Vec4(0.0f, 0.0f, 4800.0f, 1.0f));	
	myLight1->setAmbient(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
	myLight1->setDiffuse(osg::Vec4(0.25f, 0.25f, 0.25f, 0.25f));
	myLight1->setSpecular(osg::Vec4(0.0f, 0.0f, 0.0f, 0.25f));
	myLight1->setConstantAttenuation(1.0f); //设置恒衰减指数
	myLight1->setLinearAttenuation(0.0f);   //设置线性衰减指数
	myLight1->setQuadraticAttenuation(0.0f); //设置二次方衰减指数
	myLight1->setDirection(osg::Vec3(0.0, 0.0, -2000.0f)); 

	osg::ref_ptr<osg::LightSource> lightS1 = new osg::LightSource;
	lightS1->setLight(myLight1);
	lightS1->setName(gMyLightStr);
	lightS1->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);

	myroot->addChild(lightS1);
	//加入粒子系统
	osg::ref_ptr<osgParticle::PrecipitationEffect> myParticle = new osgParticle::PrecipitationEffect;
	myParticle->rain(0.15);
	myParticle->snow(0.22);
	osg::ref_ptr<osg::Fog> myFog = new osg::Fog;
	myFog->setColor(osg::Vec4(0.5, 0.5, 0.5, 0.0));
	myFog->setDensity(0.05);
	myFog->setMode(osg::Fog::EXP);
	myFog->setStart(0.0);
	myFog->setEnd(300.0);
	myParticle->setFog(myFog);

	myroot->addChild(myParticle);
	//模型控制
	myroot->setEventCallback(new CMyNodeCallback);
	//设置摄像机
	osg::ref_ptr<MyOSGCamera> pmyCamera = new MyOSGCamera();
	//设置摄像机的初始位置
	pmyCamera->setPosition(osg::Vec3f(-2.9797, 7.17492, 30)); 
	myviewer->setCameraManipulator(pmyCamera);

	//将模型放入场景
	myviewer->setSceneData(myroot.get());
	//添加帮助
	myviewer->addEventHandler(new osgViewer::HelpHandler);
	myviewer->addEventHandler(new CMyHelpHandler);
	
	//运行
	myviewer->realize();
	myviewer->run();

	return 0;
}

#include “Include.h”

#pragma once
#include <osg/Node>
#include <osg/Group>
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/CullFace>
#include <osg/Polytope>
#include <osg/BlendFunc>
#include <osg/AlphaFunc>
#include <osg/Matrixd>
#include <osg/Matrix>
#include <osg/MatrixTransform>
#include <osg/AutoTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/Material>
#include <osg/TexGen>
#include <osg/Light>
#include <osg/LightSource>
#include <osg/BoundingSphere>
#include <osg/BoundingBox>
#include <osg/Fog>
#include <osg/StateAttribute>
#include <osg/Point>
#include <osg/LineSegment>
#include <osg/TextureCubeMap>
#include <osg/TexGen>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/GraphicsWindow>
#include <osgGA/CameraManipulator>
#include <osgGA/StateSetManipulator>
#include <osgDB/ReadFile>
#include <osgDB/Registry>
#include <osgText/Text>
#include <osgWidget/WindowManager>
#include <osgWidget/Box>
#include <osgWidget/Table>
#include <osgWidget/Label>
#include <osgParticle/PrecipitationEffect>
#include <osgUtil/SmoothingVisitor>
#include <osgUtil/Optimizer>
#include <osgUtil/IntersectionVisitor>
#include <osgUtil/PolytopeIntersector>
#include <string>
#include <memory>
#include <windows.h>
#include <deque>
#include <locale.h>

using namespace std;

const unsigned int WINDOW_WIDTH       = 1300;
const unsigned int WINDOW_HEIGHT      = 650;

const unsigned int MASK_2D            = 0xF0000000;
const unsigned int MASK_3D            = 0x0F000000;


static const std::string gMyCarStr   = "mycar";
static const std::string gMySceneStr = "mysecen";
static const std::string gMyLightStr = "myLight";

#ifdef _DEBUG
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgViewerd.lib")
#pragma comment(lib, "OpenThreadsd.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgUtild.lib")
#pragma comment(lib, "osgTextd.lib")

#pragma comment(lib, "osgWidgetd.lib")
#pragma comment(lib, "glu32.lib") 
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "osgShadowd.lib")
#pragma comment(lib, "osgAnimationd.lib")
#pragma comment(lib, "osgParticled.lib")
#else
#pragma comment(lib, "osg.lib")
#pragma comment(lib, "osgDB.lib")
#pragma comment(lib, "osgViewer.lib")
#pragma comment(lib, "OpenThreads.lib")
#pragma comment(lib, "osgGA.lib")
#pragma comment(lib, "osgUtil.lib")
#pragma comment(lib, "osgText.lib")
#pragma comment(lib, "osgWidget.lib")
#pragma comment(lib, "glu32.lib") 
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "osgShadow.lib")
#pragma comment(lib, "osgAnimation.lib")
#pragma comment(lib, "osgParticle.lib")
#endif;

MyOSGCamera控制摄像机的移动方向类

#pragma once
#include "Include.h"

class MyOSGCamera :
	public osgGA::CameraManipulator
{
public:
	MyOSGCamera(void);
	~MyOSGCamera(void);
public:
	osg::Vec3f					m_vPosition;        //位置
	osg::Vec3f					m_vRotation;	    //旋转角度
	float                       m_fCarRotateZ;       //汽车转弯带动的摄像机旋转  
	float                       m_fMyRotateZ;        //玩家控制摄像机绕Z轴旋转的角度
	float						m_fMoveSpeed;	    //移动速度
	float						m_fAngle;			//屏幕角度
public:
	void setPosition(osg::Vec3f);
	void setRotatefZ(float rotatefZ);
	void resetRotateZ();
public:
	virtual void setByMatrix(const osg::Matrixd& matrix);
	virtual void setByInverseMatrix(const osg::Matrixd& matrix);
	virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);//主要事件控制器

	virtual osg::Matrixd getMatrix(void) const;
	virtual osg::Matrixd getInverseMatrix(void) const;		//得到逆矩阵
};


/**************************cpp****************************************/
#include "MyOSGCamera.h"
MyOSGCamera::MyOSGCamera(void)
{
	m_vPosition		   = osg::Vec3f(0.0, 0.0f, 5.0f);
	m_vRotation		   = osg::Vec3f(osg::PI_2-0.165f, 0.0f, 0.0f);
	m_fAngle		   = 2.5f; //左右旋转角度
	m_fCarRotateZ      = 0.0f;
	m_fMyRotateZ       = 0.0f;
}


MyOSGCamera::~MyOSGCamera(void)
{
}

void MyOSGCamera::setByMatrix(const osg::Matrixd& matrix)
{

}

void MyOSGCamera::setByInverseMatrix(const osg::Matrixd& matrix)
{

}

bool MyOSGCamera::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
{
	switch(ea.getEventType())
	{
	case osgGA::GUIEventAdapter::KEYDOWN:
		{
			if (ea.getKey() == 'a') //左转
			{
				m_fMyRotateZ += osg::DegreesToRadians(m_fAngle);
				resetRotateZ();
			}

			if (ea.getKey() == 'd')  //右转
			{
				m_fMyRotateZ -= osg::DegreesToRadians(m_fAngle);
				resetRotateZ();
			}

			if (ea.getKey() == 'w')  //抬头看
			{
				m_vRotation._v[0] += 0.015f;
				return true;
			}

			if (ea.getKey() == 's') //低头看
			{
				m_vRotation._v[0] -= 0.015f;
				return true;
			}
		}
	default:
		break;
	}

	return true;
}

osg::Matrixd MyOSGCamera::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 MyOSGCamera::getInverseMatrix(void) const
{
	return osg::Matrixd::inverse(getMatrix()); //先得到当前的视图矩阵,然后返回其逆矩阵
}

void MyOSGCamera::setPosition(osg::Vec3f pos)
{
	m_vPosition = pos;
}

void MyOSGCamera::setRotatefZ(float rotatefZ)
{
	m_fCarRotateZ = rotatefZ;
	resetRotateZ();
}

void MyOSGCamera::resetRotateZ()
{
	m_vRotation._v[2] = m_fMyRotateZ + m_fCarRotateZ;
}

CMyNodeCallback控制模型类,其中CMyNodeVisitor为自定义节点访问器。

#pragma once
#include "Include.h"
#include "MyOSGCamera.h"
#include "MyNodeVisitor.h"

class CMyNodeCallback :
	public osg::NodeCallback
{
public:
	CMyNodeCallback(void);
	virtual ~CMyNodeCallback(void);

	virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
	virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
public:
	void InitNode(osg::Node* node, osg::NodeVisitor* nv);    //初始化类中成员变量
	//碰撞检测
	void CollisionDetection(osg::Vec3d nextpos);
private:
	//场景的根节点
	osg::ref_ptr<osg::Group> m_rootGroup;
	//场景中的摄像机
	MyOSGCamera              *m_myCamera;
	//整个场景的全局光源
	osg::Light *m_myLight;
	//用于控制汽车的节点
	osg::PositionAttitudeTransform *m_myCarNode;
	//整个地图
	osg::PositionAttitudeTransform *m_mySceneNode;

	//汽车位置
	osg::Vec3						m_myCarPos;
	//摄像机位置
	osg::Vec3						m_myCameraPos;
	//汽车的行驶速度 以及 汽车绕整个场景Z轴的旋转角度
	float                            m_speed;
	float                            m_rotatef;
};

/*****************************cpp*****************************/
#include "MyNodeCallback.h"
CMyNodeCallback::CMyNodeCallback(void)
{
	m_speed        = 0.0f;
	m_rotatef      = 0.0f;
}


CMyNodeCallback::~CMyNodeCallback(void)
{
}

void CMyNodeCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
	//std::cout<<"+++++++++++CMyNodeCallback++++++++++++++++"<<std::endl;
	static bool isInit = false;
	if (!isInit)                 //在程序最开始运行的时候初始化类中成员变量
	{
		InitNode(node, nv);
		isInit = true;
	}

	if (osg::NodeVisitor::EVENT_VISITOR == nv->getVisitorType()) //判断访问器类型
	{
		//创建事件访问器并初始化
		osg::ref_ptr<osgGA::EventVisitor> ev = dynamic_cast<osgGA::EventVisitor*>(nv);
		if (ev)
		{
			osgGA::GUIActionAdapter* aa = ev->getActionAdapter();  //得到执行动作
			osgGA::EventQueue::Events& events = ev->getEvents();   //得到事件队列

			//遍历整个事件队列并处理每一个事件
			for (osgGA::EventQueue::Events::iterator itr = events.begin(); itr != events.end(); ++itr)
			{
				handle(*(*itr), *(aa));
			}
		}
	}

	//更新场景
	m_myCarPos = m_myCarNode->getPosition();
	CollisionDetection(osg::Vec3d(-m_speed*sin(m_rotatef),  m_speed*cos(m_rotatef), 0.0));
	//m_myCarPos += osg::Vec3d(-m_speed*sin(m_rotatef),  m_speed*cos(m_rotatef), 0.0);
	//m_myCarPos += osg::Vec3d(-0.5*sin(0.0),  0.5*cos(0.0), 0.0);
	m_myCarNode->setPosition(m_myCarPos);

	m_myCameraPos = m_myCarPos + osg::Vec3f(0, -100, 35)*osg::Matrixd(osg::Quat(m_rotatef,osg::Z_AXIS)); 
	m_myCamera->setPosition(m_myCameraPos);
}

bool CMyNodeCallback::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
	switch(ea.getEventType())
	{
	case osgGA::GUIEventAdapter::KEYDOWN:
		{
			if (ea.getKey() == 'i')
			{
				m_speed += 0.2f;
			}

			if (ea.getKey() == 'k')
			{
				m_speed -= 0.2f;
			}

			if (ea.getKey() == 'j')
			{
				m_rotatef += 0.02f;

				osg::Quat quat = osg::Quat(m_rotatef - osg::PI_2, osg::Z_AXIS);
				m_myCarNode->setAttitude(quat);  
				m_myCamera->setRotatefZ(m_rotatef);
			}

			if (ea.getKey() == 'l')
			{
				m_rotatef -= 0.02f;
				osg::Quat quat = osg::Quat(m_rotatef - osg::PI_2, osg::Z_AXIS);
				m_myCarNode->setAttitude(quat);  
				m_myCamera->setRotatefZ(m_rotatef);
			}
			if (ea.getKey() == 'o')
			{
				m_speed = 0.00f;
				//m_rotatef = 0.0f;
			}
			break;
		}
	default:
		break;
	}
	return true;
}

void CMyNodeCallback::InitNode(osg::Node* node, osg::NodeVisitor* nv)
{
	m_rootGroup = dynamic_cast<osg::Group*>(node);

	osg::ref_ptr<osgGA::EventVisitor> ev = dynamic_cast<osgGA::EventVisitor*>(nv);
	osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(ev->getActionAdapter());
	m_myCamera = dynamic_cast<MyOSGCamera*>(viewer->getCameraManipulator());

	//遍历节点
	CMyNodeVisitor myNodevisitor;
	myNodevisitor.SetFindNodeName(gMyCarStr);
	m_rootGroup->accept(myNodevisitor);
	m_myCarNode = dynamic_cast<osg::PositionAttitudeTransform*>(myNodevisitor.GetFindNode());

	myNodevisitor.SetFindNodeName(gMySceneStr);
	m_rootGroup->accept(myNodevisitor);
	m_mySceneNode = dynamic_cast<osg::PositionAttitudeTransform*>(myNodevisitor.GetFindNode());

	myNodevisitor.SetFindNodeName(gMyLightStr);
	m_rootGroup->accept(myNodevisitor);
	m_myLight = dynamic_cast<osg::LightSource*>(myNodevisitor.GetFindNode())->getLight();
}

void CMyNodeCallback::CollisionDetection(osg::Vec3d nextpos)
{
	if (m_speed < 0.0f)  
	{
		m_myCarPos += nextpos;
		return ;
	}
	//获取包围盒
	osg::BoundingSphere bs = m_myCarNode->getBound();
	float radius = bs.radius()/10;
	float downRotatef = m_rotatef + osg::PI_4/3;
	float upRotatef   = m_rotatef - osg::PI_4/3;

	osg::Vec3 midStart;   //中间的直线段的起点
	osg::Vec3 downStart;  //下面的直线段的起点
	osg::Vec3 upStart;    //上面的直线段的起点


	midStart = osg::Vec3(bs.center().x()-radius*sin(m_rotatef),  
		bs.center().y()+radius*cos(m_rotatef), bs.center().z());

	downStart = osg::Vec3(bs.center().x()-radius*sin(downRotatef),  
		bs.center().y()+radius*cos(downRotatef), bs.center().z());

	upStart = osg::Vec3(bs.center().x()-radius*sin(upRotatef),  
		bs.center().y()+radius*cos(upRotatef), bs.center().z());
	
	

	osg::ref_ptr<osgUtil::LineSegmentIntersector> midIntor = new osgUtil::LineSegmentIntersector(midStart, midStart+nextpos);
	osg::ref_ptr<osgUtil::LineSegmentIntersector> downIntor = new osgUtil::LineSegmentIntersector(downStart, downStart+nextpos);
	osg::ref_ptr<osgUtil::LineSegmentIntersector> upIntor = new osgUtil::LineSegmentIntersector(upStart, upStart+nextpos);

	osgUtil::IntersectionVisitor midInterVis(midIntor.get());
	osgUtil::IntersectionVisitor downInterVis(downIntor.get());
	osgUtil::IntersectionVisitor upInterVis(upIntor.get());

	m_rootGroup->accept(midInterVis);
	m_rootGroup->accept(downInterVis);
	m_rootGroup->accept(upInterVis);

	if (midIntor->containsIntersections() || downIntor->containsIntersections() || upIntor->containsIntersections())
	{

	}
	else
	{
		m_myCarPos += nextpos;
	}
}

CMyNodeVisitor 节点访问器类

#pragma once
#include "Include.h"
/************************************************************************/
/* 节点遍历器                                                            */
/************************************************************************/
class CMyNodeVisitor :
	public osg::NodeVisitor
{
public:
	CMyNodeVisitor(void);
	~CMyNodeVisitor(void);
private:
	std::string m_strfindName;
	osg::ref_ptr<osg::Node> m_myFindNode;
public:
	osg::Node *GetFindNode();
	void SetFindNodeName(const std::string &strname);
	virtual void apply(osg::Node& node);
};


/*************************************cpp***********************************/
#include "MyNodeVisitor.h"
CMyNodeVisitor::CMyNodeVisitor(void):osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
{
	m_strfindName.clear();
}

CMyNodeVisitor::~CMyNodeVisitor(void)
{
}

osg::Node* CMyNodeVisitor::GetFindNode()
{
	return m_myFindNode;
}

void CMyNodeVisitor::SetFindNodeName(const std::string &strname)
{
	m_strfindName = strname;
}

void CMyNodeVisitor::apply(osg::Node& node)
{
	if (node.getName() == m_strfindName)
	{
		m_myFindNode = &node;
	}

	traverse(node);
}

CMyHelpHandler提示帮助类

#pragma once
#include "Include.h"
class CMyHelpHandler :
	public osgGA::GUIEventHandler
{
public:
	CMyHelpHandler(void);
	~CMyHelpHandler(void);
	 virtual void getUsage(osg::ApplicationUsage&) const;
};


/*************************************cpp***********************************/
#include "MyHelpHandler.h"
CMyHelpHandler::CMyHelpHandler(void)
{
}

CMyHelpHandler::~CMyHelpHandler(void)
{
}

void CMyHelpHandler::getUsage(osg::ApplicationUsage& usage) const
{
	usage.addKeyboardMouseBinding("W","Camera up\n");
	usage.addKeyboardMouseBinding("S","Camera down\n");
	usage.addKeyboardMouseBinding("A","Camera left\n");
	usage.addKeyboardMouseBinding("D","Camera right\n");

	usage.addKeyboardMouseBinding("i","Car up\n");
	usage.addKeyboardMouseBinding("k","Car down\n");
	usage.addKeyboardMouseBinding("j","Car left\n");
	usage.addKeyboardMouseBinding("l","Car right\n");
}

运行效果图
在这里插入图片描述

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值