实验二 建立基本的游戏场景

实验二 建立基本的游戏场景

一、实验内容:

1. 建立一个简单的游戏场景;

2. 通过摄像机实现场景的切换;

3. 使用不同的光照实现阴影效果;

二、实验目的:

1. 了解Ogre程序的工作方法和Ogre场景的坐标系,掌握场景管理器、场景节点和实体的概念及其具体应用。

2. 掌握摄像机、视口的概念及其在游戏编程中的具体应用。

3. 掌握不同类型光源的使用方法和区别,熟悉阴影的产生方法。

三、实验步骤

1)、初试

首先第一步是要做出一个简单的窗口,

由于Orge现在Sample都使用了插件的机制,调试不方便,

也不利于理解真正的Orge流程,

所以翻看了些资料,直接从根本动手,

1, 首先建立一个新项目

敲入代码:

#include <Ogre.h>

#include <ExampleApplication.h>

#include <windows.h>

#include <windowsx.h>

int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd )

{

// 执行应用程序初始化:

Root * g_ogreRoot=new Root("plugins_d.cfg");

// 显示配置窗口

bool rtn = g_ogreRoot->showConfigDialog();

// 如果配置文件已经存在(已经执行过起码一次showConfigDialog ),

// 那么你可以用下面这句之间读取配置,而不需要显示配置窗口。

g_ogreRoot->restoreConfig();

// 创建渲染窗口

g_ogreRoot->initialise(true, "My Render Window"); // 这里的true 指示ogre 自动创建窗口

RenderWindow * renderWindow =g_ogreRoot->getAutoCreatedWindow();

renderWindow->setAutoUpdated(true);

// 创建场景管理器,这个TerrainSceneManager 是指地形场景管理器

SceneManager* mSceneMgr = g_ogreRoot->createSceneManager("TerrainSceneManager");

// 创建摄像机

Camera* mCamera = mSceneMgr->createCamera("PlayerCam");

mCamera->setPosition(Vector3(0,0,-300)); // 摄像机位置

mCamera->lookAt(Vector3(0,0,800)); // 摄像机朝向

// 设置渲染窗口的视口(和我们的摄像机绑定)

Viewport *vp = renderWindow->addViewport(mCamera);

vp->setBackgroundColour(ColourValue(0, 0, 0));

// 定义资源的读取目录/文件,dragon.zip 放在执行目录,这个文件可以在OgreSDK\media\packs 目录下找到

ResourceGroupManager::getSingleton().addResourceLocation(

"dragon.zip", "Zip", "General"

);

// 我把script 目录从OgreSDK\media\materials\scripts 复制到执行目录下了,龙的皮肤着色需要用到某个脚本

ResourceGroupManager::getSingleton().addResourceLocation(

"scripts", "FileSystem", "General"

);

// 初始化资源管理器

ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

// 读取龙的模型

Entity * ent = mSceneMgr->createEntity("dragon", "dragon.mesh");

// 把模型放入场景管理器

mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);

// 开始渲染

g_ogreRoot->startRendering();

return 0;

}

代码不难理解,相比起手动建立一个完整的DX来说已是非常简单了,

继续,定义好一个plugins_d.cfg文件,作为Orge的初始化配置

# Defines plugins to load

# Define plugin folder

PluginFolder=.

# Define plugins

Plugin=RenderSystem_Direct3D9_d

# Plugin=RenderSystem_Direct3D10_d

# Plugin=RenderSystem_Direct3D11_d

Plugin=RenderSystem_GL_d

# Plugin=RenderSystem_GLES_d

Plugin=Plugin_ParticleFX_d

Plugin=Plugin_BSPSceneManager_d

Plugin=Plugin_CgProgramManager_d

Plugin=Plugin_PCZSceneManager_d

Plugin=Plugin_OctreeZone_d

Plugin=Plugin_OctreeSceneManager_d

配置文件既是定义了相关的插件配置,咱是xp,跑不了DX10/11,

貌似CMake也做好了判断,DX10的RenderSystem也找不到。。。

2,配置项目

敲好了代码还远远不够,加入Orge的各个配件可是关键,

DXSDK早已配置完成,这里主要把Orge一个个耐心加入:

1.包含文件

\ogre-v1-7-0\Dependencies\include

\ogre-v1-7-0\Samples\Common\include

\ogre-v1-7-0\OgreMain\include

\ogre-v1-7-0\include

2.库文件

\ogre-v1-7-0\Dependencies\lib\Release

\ogre-v1-7-0\Dependencies\lib\Debug

\ogre-v1-7-0\lib\Release

\ogre-v1-7-0\lib\Debug

clip_image002

clip_image004

这些可确是重中之重,仔细检查后F7,F5

3,调试

编译非常顺利,比起OrgeSDK,这可算是从石器时代回到了现代文明,

可美好的东西哪有那么容易得来,

报错了,

没办法,兵来将挡水来土掩,

拿起Debug的利器,

几经跟踪后发现;

clip_image006

应该是动态库的问题

clip_image008

终于发现了:RenderSystem_Direct3D9_d.dll!!

clip_image010

可是一时还搞不明白Orge的复杂读取机制,只好直接暴力破解,

在Orge下找到DLL

clip_image012

直接复制入系统目录

clip_image014

问题迎刃而解:

clip_image016

4,Debug II

可现在就庆祝胜利还是太早了些,错误又来了,

clip_image018

呵呵,粗枝大叶了,Media忘记拷贝过来,

clip_image020

F5,一切搞定:

clip_image022

2)、这些都不够,我要动起来

1,架构

当前的框架还是十分的稚嫩,

到Orge官网逛了下后决定使用Ogre Wiki Tutorial Framework来进行接下来的工作

clip_image024

一个小插曲,下来的压缩包解压之后竟然是一个无后缀文件,猜测还是一个压缩包,加了个rar,成功

clip_image026

一个全新的窗口来到了,呵呵~~~

2, 主循环

读懂了

clip_image028

的大体结构,

重写一个

void TutorialApplication::createScene(void)

{

mCamera->setPosition(Vector3(0,30,-300)); // 摄像机位置

mCamera->lookAt(Vector3(0,0,800)); // 摄像机朝向

// 定义资源的读取目录/文件,dragon.zip 放在执行目录,这个文件可以在OgreSDK\media\packs 目录下找到

ResourceGroupManager::getSingleton().addResourceLocation(

"dragon.zip", "Zip", "General"

);

// 我把script 目录从OgreSDK\media\materials\scripts 复制到执行目录下了,龙的皮肤着色需要用到某个脚本

ResourceGroupManager::getSingleton().addResourceLocation(

"scripts", "FileSystem", "General"

);

// 初始化资源管理器

ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

// 读取龙的模型

Entity * ent = mSceneMgr->createEntity("dragon", "dragon.mesh");

// 把模型放入场景管理器

mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);

// 开始渲染

SceneNode* node=mSceneMgr->getRootSceneNode();

float scal=1.0f;

}

结果非常顺利,整个三维世界已经触手可及:

(框架封装好了输入控制,可以直接操作摄像机)

clip_image030

3, 接下来,那就让飞龙动起来吧:

结加入代码,获得更多的控制权

clip_image032

if(arg.key == OIS::KC_B)

{

m_pNode->showBoundingBox(!m_pNode->getShowBoundingBox());

}

if(arg.key == OIS::KC_Z)

{

m_fScale=1.1f;

m_pNode->scale(m_fScale,m_fScale,m_fScale);

}

else if(arg.key == OIS::KC_X)

{

m_fScale=0.9f;

m_pNode->scale(m_fScale,m_fScale,m_fScale);

}

if(arg.key == OIS::KC_W)

{

m_pNode->pitch(Radian(0.1f));

}

else if(arg.key == OIS::KC_S)

{

m_pNode->pitch(Radian(-0.1f));

}

if(arg.key == OIS::KC_A)

{

m_pNode->yaw(Radian(0.1f));

}

else if(arg.key == OIS::KC_D)

{

m_pNode->yaw(Radian(-0.1f));

}

clip_image034

4,细节

一开始,缩放只能一直缩或者一直放,

看了源代码,发现Orge下的scal的参数传进去是用了个*,

明白之后,传入1.1/0.9,问题解决

接下来,旋转始终有问题,

发现快捷键与现有的摄像机的快捷键有了冲突,

改正之后,还有个问题就是单帧分离开,就是要一直不停的按才可以,这个很郁闷,

打算写个状态,来记录下键位。。。

clip_image036

clip_image038

4, 继续改进

心动不如行动,加入了一个KeyState记录键位信息,

加入Update作为响应:

clip_image040

响应键位变化:

clip_image042

整体操作现在终于变得非常流畅了:

clip_image044

3)、上帝说,要有光

基本操作都已经实现,那么接下来就加入光影效果吧:

建立一个新工程,这回直接改写基类,上回写的架构太过罗嗦了,

其它基本保持一致,改动createScene,载入模型,加入灯光

void BasicTutorial2::createScene(void)

{

mSceneMgr->setAmbientLight(Ogre::ColourValue(0, 0, 0));

mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);

Ogre::Entity* entNinja = mSceneMgr->createEntity("Ninja", "ninja.mesh");

entNinja->setCastShadows(true);

//mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(entNinja);

m_pNode->attachObject(entNinja);

Ogre::Plane plane(Ogre::Vector3::UNIT_Y, 0);

Ogre::MeshManager::getSingleton().createPlane("ground", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,

plane, 1500, 1500, 20, 20, true, 1, 5, 5, Ogre::Vector3::UNIT_Z);

Ogre::Entity* entGround = mSceneMgr->createEntity("GroundEntity", "ground");

mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(entGround);

entGround->setMaterialName("Examples/Rockwall");

entGround->setCastShadows(false);

Ogre::Light* pointLight = mSceneMgr->createLight("pointLight");

pointLight->setType(Ogre::Light::LT_POINT);

pointLight->setPosition(Ogre::Vector3(0, 150, 250));

pointLight->setDiffuseColour(1.0, 0.0, 0.0);

pointLight->setSpecularColour(1.0, 0.0, 0.0);

Ogre::Light* directionalLight = mSceneMgr->createLight("directionalLight");

directionalLight->setType(Ogre::Light::LT_DIRECTIONAL);

directionalLight->setDiffuseColour(Ogre::ColourValue(.25, .25, 0));

directionalLight->setSpecularColour(Ogre::ColourValue(.25, .25, 0));

directionalLight->setDirection(Ogre::Vector3( 0, -1, 1 ));

Ogre::Light* spotLight = mSceneMgr->createLight("spotLight");

spotLight->setType(Ogre::Light::LT_SPOTLIGHT);

spotLight->setDiffuseColour(0, 0, 1.0);

spotLight->setSpecularColour(0, 0, 1.0);

spotLight->setDirection(-1, -1, 0);

spotLight->setPosition(Ogre::Vector3(300, 300, 0));

spotLight->setSpotlightRange(Ogre::Degree(35), Ogre::Degree(50));

}

Debug it ,只要正确地配好SDK就万事大吉了,

不得不说,Ogre真的是太方便了,想当初自学ShadowVolume和ShadowMap不知死了多少脑细胞,废了多少周折,现在好了,So easy

clip_image046

4)、骨骼动画

四、实验数据及处理结果

结果均以截图给出,代码,工程附带。。。

五、思考讨论题或体会或对改进实验的建议

代码Ogre真的很简单,尤其是有了一定基础之后,看他的代码真的是一种享受,好吧,再接再厉,继续探索吧!

原文地址:https://www.cnblogs.com/Zephyroal/p/1947509.html