实验二 建立基本的游戏场景
实验二 建立基本的游戏场景
一、实验内容:
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
这些可确是重中之重,仔细检查后F7,F5
3,调试
编译非常顺利,比起OrgeSDK,这可算是从石器时代回到了现代文明,
可美好的东西哪有那么容易得来,
报错了,
没办法,兵来将挡水来土掩,
拿起Debug的利器,
几经跟踪后发现;
应该是动态库的问题
终于发现了:RenderSystem_Direct3D9_d.dll!!
可是一时还搞不明白Orge的复杂读取机制,只好直接暴力破解,
在Orge下找到DLL
直接复制入系统目录
问题迎刃而解:
4,Debug II
可现在就庆祝胜利还是太早了些,错误又来了,
呵呵,粗枝大叶了,Media忘记拷贝过来,
F5,一切搞定:
(2)、这些都不够,我要动起来
1,架构
当前的框架还是十分的稚嫩,
到Orge官网逛了下后决定使用Ogre Wiki Tutorial Framework来进行接下来的工作
一个小插曲,下来的压缩包解压之后竟然是一个无后缀文件,猜测还是一个压缩包,加了个rar,成功
一个全新的窗口来到了,呵呵~~~
2, 主循环
读懂了
的大体结构,
重写一个
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;
}
结果非常顺利,整个三维世界已经触手可及:
(框架封装好了输入控制,可以直接操作摄像机)
3, 接下来,那就让飞龙动起来吧:
结加入代码,获得更多的控制权
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));
}
4,细节
一开始,缩放只能一直缩或者一直放,
看了源代码,发现Orge下的scal的参数传进去是用了个*,
明白之后,传入1.1/0.9,问题解决
接下来,旋转始终有问题,
发现快捷键与现有的摄像机的快捷键有了冲突,
改正之后,还有个问题就是单帧分离开,就是要一直不停的按才可以,这个很郁闷,
打算写个状态,来记录下键位。。。
4, 继续改进
心动不如行动,加入了一个KeyState记录键位信息,
加入Update作为响应:
响应键位变化:
整体操作现在终于变得非常流畅了:
(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
(4)、骨骼动画
四、实验数据及处理结果
结果均以截图给出,代码,工程附带。。。
五、思考讨论题或体会或对改进实验的建议
代码Ogre真的很简单,尤其是有了一定基础之后,看他的代码真的是一种享受,好吧,再接再厉,继续探索吧!