当前位置: 首页 > 工具软件 > OGRE > 使用案例 >

OGRE(七)

关宏毅
2023-12-01
#include "OGRE/Ogre.h"
#include "OIS/OIS.h"


class MyFrameListener:public Ogre::FrameListener
{
public:

	bool frameStarted(const Ogre::FrameEvent &evt)
	{
		//std::cout<<"Frame Start"<<std::endl;

		bool walked = false;  
		Ogre::Vector3 SinbadTranslate(0,0,0); 

		_key->capture();

		if (_key->isKeyDown(OIS::KC_ESCAPE))
		{
			return false;
		}

		Ogre::Vector3 translate(0,0,0);

		if(_key->isKeyDown(OIS::KC_W))
		{
			translate += Ogre::Vector3(0,0,-10);
		}
		if(_key->isKeyDown(OIS::KC_S))
		{
			translate += Ogre::Vector3(0,0,10);
		}
		if(_key->isKeyDown(OIS::KC_A))
		{
			translate += Ogre::Vector3(-10,0,0);
		}
		if(_key->isKeyDown(OIS::KC_D))
		{
			translate += Ogre::Vector3(10,0,0);
		}

		if(_key->isKeyDown(OIS::KC_UP))  
		{  
			SinbadTranslate += Ogre::Vector3(0,0,-1);  
			_rotation = 0.0f;  
			walked = true;  
		}  
		if(_key->isKeyDown(OIS::KC_DOWN))  
		{  
			SinbadTranslate += Ogre::Vector3(0,0,1);  
			_rotation = 3.14f;
			walked = true;  
		}  
		if(_key->isKeyDown(OIS::KC_LEFT))  
		{  
			SinbadTranslate += Ogre::Vector3(-1,0,0);  
			_rotation = 1.57f;  
			walked = true;  
		}  
		if(_key->isKeyDown(OIS::KC_RIGHT))  
		{  
			SinbadTranslate += Ogre::Vector3(1,0,0);  
			_rotation = -1.57f;  
			walked = true;  
		}  

		if (walked)  
		{  
			_aniStateBase->setEnabled(true);  
			//_aniStateTop->setEnabled(true);  
			_aniStateIdle->setEnabled(false);  
			if (_aniStateBase->hasEnded())  
			{  
				_aniStateBase->setTimePosition(0.0f);  
			}  
			/*if (_aniStateTop->hasEnded())  
			{  
				_aniStateTop->setTimePosition(0.0f);  
			}  */
		}  
		else  
		{  
			_aniStateBase->setEnabled(false);  
			//_aniStateTop->setEnabled(false);  
			_aniStateIdle->setEnabled(true);  
			_aniStateBase->setTimePosition(0.0f);  
			//_aniStateTop->setTimePosition(0.0f);  
		}  

		if (_mouse->getMouseState().buttonDown(OIS::MB_Left))  
		{  
			_aniStateSword->setEnabled(true);

			if (_aniStateSword->hasEnded())      //关闭动作循环再加上这个,终于只挥一次刀了  
			{  
				_aniStateSword->setTimePosition(0.0f);  
			}  
		}  

		if (_key->isKeyDown(OIS::KC_LSHIFT))  
		{  
			_movementSpeed = 100.0f;  
		}  


		_cam->moveRelative(translate*evt.timeSinceLastFrame * _movementSpeed);

		_mouse->capture();
		float rotX = _mouse->getMouseState().X.rel * evt.timeSinceLastFrame * -1;
		float rotY = _mouse->getMouseState().Y.rel * evt.timeSinceLastFrame * -1;
		_cam->yaw(Ogre::Radian(rotX));
		_cam->pitch(Ogre::Radian(rotY));

		//_sinbadNode->setPosition(_cam->getPosition()+translate);

		_aniStateBase->addTime(evt.timeSinceLastFrame);      //运动自从上一次更新到现在已经过去多长时间  
		//_aniStateTop->addTime(evt.timeSinceLastFrame);   //不使用这个函数的话,动作是不会播放的  
		_aniStateIdle->addTime(evt.timeSinceLastFrame);
		_aniStateSword->addTime(evt.timeSinceLastFrame);

		_sinbadNode->translate(SinbadTranslate * evt.timeSinceLastFrame * _WalkingSpeed);  
		_sinbadNode->resetOrientation();       //重置旋转,因为我们要的是绝对的旋转而不是相对的旋转  
		_sinbadNode->yaw(Ogre::Radian(_rotation));
		_camPivot->setPosition(_sinbadNode->getPosition()+Ogre::Vector3(0,30,0));
		_camNode->setPosition(_camPivot->getPosition()+((Ogre::SceneNode*)_camPivot->getChild("mCameraGoal"))->getPosition());
		return true;
	}

	bool frameEnded(const Ogre::FrameEvent& evt)
	{
		//std::cout<<"Frame End"<<std::endl;
		return true;
	}

	bool frameRenderingQueued(const Ogre::FrameEvent& evt)
	{
		//std::cout<<"Frame Queued"<<std::endl;
		return true;
	}

	MyFrameListener(Ogre::RenderWindow* win, Ogre::Camera* cam, Ogre::Viewport* viewport, Ogre::SceneNode* sinbadNode)
	{
		_sinbadNode = sinbadNode;

		_camPivot = (Ogre::SceneNode*)cam->getSceneManager()->getRootSceneNode()->getChild("mCameraPivot");
		_camNode = (Ogre::SceneNode*)cam->getSceneManager()->getRootSceneNode()->getChild("mCameraNode");


		//暂时不知道怎么从节点中调用实体,放弃
		_ent = (Ogre::Entity*)sinbadNode->getAttachedObject("Sinbad");
		//_ent = ent;

		_cam = cam;
		_movementSpeed = 50.0f;

		OIS::ParamList pl;
		unsigned int windowHandle = 0;
		std::ostringstream windowHandleStr;		//该类通常用于执行C风格的串流的输出操作,格式化字符串,避免申请大量的缓冲区,替代sprintf

		win->getCustomAttribute("WINDOW",&windowHandle);
		windowHandleStr << windowHandle;	//格式化 
		pl.insert(std::make_pair("WINDOW",windowHandleStr.str()));

		_man = OIS::InputManager::createInputSystem(pl);
		_key = static_cast<OIS::Keyboard*>(_man->createInputObject(OIS::OISKeyboard,false));
		_mouse = static_cast<OIS::Mouse*>(_man->createInputObject(OIS::OISMouse,false));

		_viewport = viewport;
		_comp1 = false;
		_comp2 = false;
		_comp3 = false;
		_down1 = false;
		_down2 = false;
		_down3 = false;


		_aniStateIdle = _ent->getAnimationState("Idle3");  
		_aniStateIdle->setEnabled(true);  
		_aniStateIdle->setLoop(true);  
		_aniStateBase = _ent->getAnimationState("Walk");  //从实体中获取动作指针  
		_aniStateBase->setEnabled(false);    //是否可用  
		_aniStateBase->setLoop(false);       //是否循环  
		/*_aniStateTop = _ent->getAnimationState("RunTop");  
		_aniStateTop->setEnabled(false);  
		_aniStateTop->setLoop(false);  */
		_aniStateSword = _ent->getAnimationState("Attack3");  
		//_aniStateSword->getLength();
		_aniStateSword->setLoop(false); 

		_WalkingSpeed = 50.0f;  
		_rotation = 0.0f; 

		//_sinbadNode->attachObject(_cam);

	}

	~MyFrameListener()
	{
		_man->destroyInputObject(_key);
		_man->destroyInputObject(_mouse);
		OIS::InputManager::destroyInputSystem(_man);

	}

private:

	OIS::InputManager* _man;
	OIS::Keyboard* _key;
	OIS::Mouse* _mouse;
	Ogre::Camera* _cam;
	float _movementSpeed;
	Ogre::Viewport* _viewport;
	bool _comp1, _comp2, _comp3;
	bool _down1, _down2, _down3;
	Ogre::SceneNode* _sinbadNode;

	float _WalkingSpeed;    //控制走路的速度  
	float _rotation;    //控制旋转

	Ogre::Entity* _ent; //想要运动的实体  
	Ogre::AnimationState* _aniStateBase;    //运动状态指针  
	Ogre::AnimationState* _aniStateTop;  
	Ogre::AnimationState* _aniStateIdle;  
	Ogre::AnimationState* _aniStateSword; 

	Ogre::SceneNode* _camPivot;
	Ogre::SceneNode* _camNode;

};

class MyApplication
{
private:

	Ogre::SceneManager* _sceneManager;	//场景管理器
	Ogre::Root* _root;	//根节点
	Ogre::SceneNode* _sinbadNode;
	MyFrameListener* _listener;
	bool _keepRunning;
	Ogre::Entity* _ent;
	Ogre::SceneNode* mCameraPivot; 
	Ogre::SceneNode* mCameraGoal;
	Ogre::SceneNode* mCameraNode;


public:
	
	//载入资源
	void loadResources()
	{
		Ogre::ConfigFile cf;	//助手类,用于加载配置文件
		cf.load("resources_d.cfg");		//载入配置文件

		Ogre::ConfigFile::SectionIterator sectionIter =	cf.getSectionIterator();//得到一个遍历块的迭代器
		Ogre::String sectionName, typeName, dataname;	//块名,键,值
		
		//开始通过迭代器遍历资源
		while (sectionIter.hasMoreElements())
		{
			sectionName = sectionIter.peekNextKey();	//得到块

			Ogre::ConfigFile::SettingsMultiMap *settings = sectionIter.getNext();	//得到map
			Ogre::ConfigFile::SettingsMultiMap::iterator i;		//定义一个map的迭代器

			for (i = settings->begin(); i != settings->end(); ++i)	//对块里头的键-值进行迭代
			{
				typeName = i->first;	//获得键
				dataname = i->second;	//获得值

				//根据块,键,值来载入资源
				Ogre::ResourceGroupManager::getSingleton().addResourceLocation(dataname, typeName, sectionName);
			}
		}
		//初始化所有的资源组
		Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
	}

	//创建场景
	void createScene()
	{
		_ent = _sceneManager->createEntity("Sinbad","ninja.mesh");
		_sinbadNode = _sceneManager->getRootSceneNode()->createChildSceneNode("SinbadNode",Ogre::Vector3::UNIT_Y*5);
		_sinbadNode->attachObject(_ent);
		_sinbadNode->setScale(0.1f,0.1f,0.1f);
		_sinbadNode->setPosition(Ogre::Vector3(0,-10,0));

		//定义平面  
		Ogre::Plane plane(Ogre::Vector3::UNIT_Y, -10);  
		Ogre::MeshManager::getSingleton().createPlane("plane",Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane,1500,1500,200,200,true,1,5,5,Ogre::Vector3::UNIT_Z);  

		//平面实体化,并作为场景根节点的子节点  
		Ogre::Entity* ent = _sceneManager->createEntity("LightPlaneEntity", "plane");  
		_sceneManager->getRootSceneNode()->createChildSceneNode()->attachObject(ent);  
		ent->setMaterialName("Examples/BeachStones"); 

		//定义个灯光
		Ogre::Light* light = _sceneManager->createLight("light1");
		light->setType(Ogre::Light::LT_DIRECTIONAL);
		light->setDirection(Ogre::Vector3(1,-1,0));

		//_sceneManager->setShadowTechnique();    
	}

	//开始渲染,该函数的一切似乎只是初始化
	int startup()
	{
		_root = new Ogre::Root("plugins_d.cfg");	//载入插件

		if(!_root->showConfigDialog())	//弹出黑框框,如果出错或者用户点取消则返回
		{
			return -1;
		}

		//通过root,初始化-----渲染窗口和场景管理器
		Ogre::RenderWindow* window = _root->initialise(true,"Ogre3D	Beginners Guide");
		_sceneManager = _root->createSceneManager(Ogre::ST_GENERIC);

		//天空盒资源暂时还不知道如何载入,所以不能调用天空盒
		//_sceneManager->setSkyBox(true, "Examples/SpaceSkyBox", 50 );

		//通过场景管理器实例化------摄像头
		Ogre::Camera* camera = _sceneManager->createCamera("Camera");
		camera->setPosition(Ogre::Vector3(0,0,50));
		camera->lookAt(Ogre::Vector3(0,0,0));
		camera->setNearClipDistance(5);

		//camera->setFixedYawAxis(true);

		//通过渲染窗口和摄像机实例化------视口
		Ogre::Viewport* viewport = window->addViewport(camera);
		viewport->setBackgroundColour(Ogre::ColourValue(0.0,0.0,0.0));	//设置视口为黑色
		camera->setAspectRatio(Ogre::Real(viewport->getActualWidth())/Ogre::Real(viewport->getActualHeight()));
		
		//放置摄像机
		mCameraPivot = camera->getSceneManager()->getRootSceneNode()->createChildSceneNode("mCameraPivot");
		mCameraGoal = mCameraPivot->createChildSceneNode("mCameraGoal",Ogre::Vector3(0, 0, 15));
		mCameraNode = camera->getSceneManager()->getRootSceneNode()->createChildSceneNode("mCameraNode");
		mCameraNode->setPosition(mCameraPivot->getPosition() + mCameraGoal->getPosition());

		camera->setNearClipDistance(0.1);
		camera->setFarClipDistance(2000);
		mCameraNode->attachObject(camera);

		loadResources();	//载入资源
		createScene();		//画画

		_listener = new MyFrameListener(window,camera,viewport,_sinbadNode);
		_root->addFrameListener(_listener);



		//打印所有动作
		Ogre::AnimationStateSet* set = _ent->getAllAnimationStates();
		Ogre::AnimationStateIterator iter = set->getAnimationStateIterator();
		while(iter.hasMoreElements())
		{
			std::cout << iter.getNext()->getAnimationName() << std::endl;
		}

		//因为剧情需要,把startRendering注释了╮(╯▽╰)╭
		//_root->startRendering(); //开始渲染,因为我们给了root很多东西,他就在他的循环里头自己玩了,不会返回

		return 0;
	}

	void renderOneFrame()
	{
		Ogre::WindowEventUtilities::messagePump();
		_keepRunning = _root->renderOneFrame();
	}

	bool keepRunning()
	{
		return _keepRunning;
	}

	MyApplication()
	{
		_sceneManager = NULL;
		_root = NULL;
		_listener = NULL;
	}

	~MyApplication()
	{
		delete _root;
		delete _listener;
	}
};
int main()
{
/*	Ogre::Root* root = new Ogre::Root("plugins_d.cfg");

	if (!root->showConfigDialog())
	{
		return -1;
	}

	Ogre::RenderWindow* window = root->initialise(true,"Ogre3D Beginners Guide");

	Ogre::SceneManager* sceneManager = root->createSceneManager(Ogre::ST_GENERIC);

	Ogre::Camera* camera = sceneManager->createCamera("Camera");
	camera->setPosition(0,0,50);
	camera->lookAt(0,0,0);
	camera->setNearClipDistance(5);

	Ogre::Viewport* viewport = window->addViewport(camera);
	viewport->setBackgroundColour(Ogre::ColourValue(0,0,0));

	camera->setAspectRatio(Ogre::Real(viewport->getActualWidth())/Ogre::Real(viewport->getActualHeight()));
	
	Ogre::ConfigFile cf;
	cf.load("resources_d.cfg");
	Ogre::ConfigFile::SectionIterator sectionIter = cf.getSectionIterator();  //迭代器好像都不是指针

	Ogre::String sectionName, typeName, dataname;
	while (sectionIter.hasMoreElements())
	{
		sectionName = sectionIter.peekNextKey();

		Ogre::ConfigFile::SettingsMultiMap *settings = sectionIter.getNext();
		Ogre::ConfigFile::SettingsMultiMap::iterator i;

		for (i = settings->begin(); i != settings->end(); ++i)
		{
			typeName = i->first;
			dataname = i->second;
			Ogre::ResourceGroupManager::getSingleton().addResourceLocation(dataname,typeName,sectionName);
		}
	}

	//Ogre::ResourceGroupManager::getSingleton().addResourceLocation("../../Media/packs/Sinbad.zip","Zip");
	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();


	Ogre::Entity* ent = sceneManager->createEntity("Sinbad.mesh");
	sceneManager->getRootSceneNode()->attachObject(ent);

	root->startRendering();*/

	MyApplication app;
	app.startup();

	while(app.keepRunning())
	{
		app.renderOneFrame();
	}

	return 0;
}

 类似资料: