这几日折腾了一下Ogre的文件系统,我总想把它的文件系统从它的庞大代码堆中分理出来,这样我就可以重复利用这一部分代码,^_^,经过一翻测试,Ogre的文件系统完全被我分理处来,而且非常好用,我把他加入到我原来的2D项目中,工作非常顺利,Ogre抽象的他好了,以至于我几乎不用怎么担心他的兼容性,下面就简要介绍一下分离方法。
首先,我要说得是:我所分离的部分只是文件管理部分,不包括Ogre的资源相关部分,涉及到Ogre的资源部分不属于本文探讨范围,其次,Ogre文件系统相关知识可以从网上下载《Ogre分析之文件系统》仔细研究,Mythma的文档给了我很大的帮助,再次一并感谢。
Ogre文件系统的核心是Archive和DataStream,从Ogre继承结构可以看出,他们都是抽象基类,Ogre自带了Ogre::FileSystemArchive和Ogre::ZipArchive,分别用于实现文件夹和压缩包,如果你要实现自己的文件格式,比如自己的数据包,一个包里有多个文件,只需写个类似ZipArchive的类,然后向ArchiveManager注册即可,ArchiveManager是文件管理类。DataStream提供了操纵文件的统一接口,我在下面使用了size()和read(),他有四个派生类。
在这次操作种,找到OgreArchive.h,OgreArchiveFactory.h,OgreArchiveManager.h,OgreZip.h及其他们对应的实现文件(如果有),把他们复制出来,去掉这些头文件中关于资源管理的信息,当然,还有其他相关文件需要提取,例如Log方面的,智能指针也是,还有Singleton等,这些在我上次试验中已经提取完毕,这里不再重复,这篇文章只是那篇文章的补充,测试代码判断如下,实现了用Ogre接口从文件夹和Zip读取数据给DX原始API使用。
ArchiveFactory *mFileSystemArchiveFactory = new FileSystemArchiveFactory();
ArchiveManager::getSingleton().addArchiveFactory( mFileSystemArchiveFactory );
FileSystemArchive *pFileSystem = static_cast<FileSystemArchive *>(m_ArchiveMgr.load("../Media", "FileSystem"));
StringVectorPtr pStrVectorFileSystem = pFileSystem->list(true);
ArchiveFactory *mZipArchiveFactory = new ZipArchiveFactory();
ArchiveManager::getSingleton().addArchiveFactory( mZipArchiveFactory );
ZipArchive *pZip = static_cast<ZipArchive *>(m_ArchiveMgr.load("../Media/Package/OgreCore.zip", "Zip"));
StringVectorPtr pStrVectorZip = pZip->list(true);
/* 从文件中读取数据
DataStreamPtr pDataStream = pFileSystem->open("Texture/mm.jpg");
size_t s = pDataStream.getPointer()->size();
char *pBuf = new char[s];
pDataStream.getPointer()->read(static_cast<void *>(pBuf), s);
*/
//从Zip读取数据
DataStreamPtr pDataStream = pZip->open("OgreCore/ogretext.png");
size_t s = pDataStream.getPointer()->size();
char *pBuf = new char[s];
pDataStream.getPointer()->read(static_cast<void *>(pBuf), s);
//自定义类,实际是调用D3DXCreateTextureFromFileInMemoryEx
CScene9::CreateGraph2D(&graph);
graph.LoadFromMemory(pBuf, s);
posted @
2006-12-05 21:57 gogoplayer 阅读(648) |
评论 (0) |
编辑 收藏
总的来说,非常的好用,Ogre在即将推出的1.4版本中将完全去处原来破破烂烂的输入部分,取而代之得是OIS(Object-oriented Input Library),对我来说,Ogre去除自带的输入系统是个非常好的消息,这本来就不是一个图形渲染系统该有的,OIS出现的太及时了,OIS的作者是Ogre的MVP,我看过他的代码,功力深厚,虽然现在OIS功能还不是很高,但是比原来的那个还是要好的多,提供了立即模式和缓冲模式(可共用),也就是设计模式那一套路,用个监听器得到消息,这样的封装用起来非常简单。
class EventHandler : public KeyListener, public MouseListener, public JoyStickListener
{
public:
EventHandler() {}
~EventHandler() {}
bool keyPressed( const KeyEvent &arg ) {
std::cout << "\nKeyPressed {" << arg.key
<< ", " << ((Keyboard*)(arg.device))->getAsString(arg.key)
<< "} || Character (" << (char)arg.text << ")" << std::endl;
return true;
}
bool keyReleased( const KeyEvent &arg ) {
if( arg.key == KC_ESCAPE || arg.key == KC_Q )
appRunning = false;
return true;
}
bool mouseMoved( const MouseEvent &arg ) {
const OIS::MouseState& s = arg.state;
std::cout << "\nMouseMoved: Abs("
<< s.abX << ", " << s.abY << ", " << s.abZ << ") Rel("
<< s.relX << ", " << s.relY << ", " << s.relZ << ")";
return true;
}
bool mousePressed( const MouseEvent &arg, MouseButtonID id ) {
std::cout << "\nMousePressed: " << id << " time[" << arg.timeStamp << "]";
return true;
}
bool mouseReleased( const MouseEvent &arg, MouseButtonID id ) {
std::cout << "\nMouseReleased: " << id << " time[" << arg.timeStamp << "]";
return true;
}
bool buttonPressed( const JoyStickEvent &arg, int button ) {
std::cout << "\nJoy ButtonPressed: " << button << " time[" << arg.timeStamp << "]";
return true;
}
bool buttonReleased( const JoyStickEvent &arg, int button ) {
return true;
}
bool axisMoved( const JoyStickEvent &arg, int axis )
{
std::cout << "\nJoy Axis " << axis << " " << arg.state.mAxes[axis].abX
<< " " << arg.state.mAxes[axis].abY;
return true;
}
bool povMoved( const JoyStickEvent &arg, int pov )
{
std::cout << "\nJoy POV" << pov << " ";
if( arg.state.mPOV[pov].direction & Pov::North ) //Going up
std::cout << "North";
else if( arg.state.mPOV[pov].direction & Pov::South ) //Going down
std::cout << "South";
if( arg.state.mPOV[pov].direction & Pov::East ) //Going right
std::cout << "East";
else if( arg.state.mPOV[pov].direction & Pov::West ) //Going left
std::cout << "West";
if( arg.state.mPOV[pov].direction == Pov::Centered ) //stopped/centered out
std::cout << "Centered";
return true;
}
};
上面的代码就是定义了一个集键盘、鼠标、手柄消息控制于一身的监听器,有相应事件产生就会调用相应的函数,使用及其方便,我把OIS的VC8版本接入到我原来的一个2D引擎中,工作非常顺利,这也使我彻底的淘汰了原来不良的设计,如果你有自己的引擎,你也可以试一下,OIS 下载 http://sourceforge.net/projects/wgois/ ,再来个Ogre对于他的介绍 http://www.ogre3d.org/wiki/index.php/Using_OIS 。
posted @
2006-11-29 01:11 gogoplayer 阅读(1529) |
评论 (8) |
编辑 收藏
绝对轻量级的声音引擎,audiere,支持跨平台,可以去http://sourceforge.net/projects/audiere/下载,再给个小例子,^_^
用VC6或者其他配置好工程,建个控制台程序即可
#include <iostream>
using namespace std;
#include "audiere.h"
audiere::AudioDevicePtr device(audiere::OpenDevice());
audiere::OutputStreamPtr stream(audiere::OpenSound(device, "music.wav", false));
int main()
{
stream->setRepeat(true);
stream->setVolume(0.5f); // 50% volume
stream->play();
int a;
cin >> a;
return 0;
}
posted @
2006-11-29 00:54 gogoplayer 阅读(728) |
评论 (1) |
编辑 收藏
其实就是手动配置渲染系统,去掉Ogre自带的对话框,如果会用Ogre的基本框架,下列代码很容易理解
bool RPGApp::configure(void)
{
// Show the configuration dialog and initialise the system
// You can skip this and use root.restoreConfig() to load configuration
// settings if you were sure there are valid ones saved in ogre.cfg
//if(mRoot->showConfigDialog())
RenderSystemList *rsList = mRoot->getAvailableRenderers();
int c=0;
bool foundit = false;
RenderSystem *selectedRenderSystem=0;
while(c < (int) rsList->size()){
selectedRenderSystem = rsList->at(c);
String rname = selectedRenderSystem->getName();
if(rname.compare("Direct3D9 Rendering Subsystem")==0){
foundit=true;
break;
}
c++; // <-- oh how clever
}
if(!foundit) return false; //we didn't find it...
//we found it, we might as well use it!
selectedRenderSystem->setConfigOption("Full Screen","Yes");
selectedRenderSystem->setConfigOption("Video Mode","1024 x 768 @ 32-bit colour");
selectedRenderSystem->setConfigOption("Allow NVPerfHUD","No");
selectedRenderSystem->setConfigOption("Anti aliasing","None");
selectedRenderSystem->setConfigOption("Floating-point mode","Fastest");
//selectedRenderSystem->setConfigOption("Rendering Device","RADEON 9200");
selectedRenderSystem->setConfigOption("VSync","No");
mRoot->setRenderSystem(selectedRenderSystem);
mWindow = mRoot->initialise(true, "Dire Desire");
return true;
}
posted @
2006-11-29 00:45 gogoplayer 阅读(661) |
评论 (0) |
编辑 收藏
Terrain Scene Manager参数详解
在场景中地形的形状和染色从一张高度图,一张地形纹理和一张细节贴图中被计算出来。高度图是一张灰度图,每个象素表现一个高度值,0表示地平面,255表示地形最高点。
地形上面覆盖的的那层纹理被拉伸。这些地形纹理具有代表性的是斑驳的褐色,绿色,白色或者灰色适合于地表,草,雪或岩石地形。地形纹理通常比要覆盖地形小的多,所以近看时通常很模糊。为了解决这个问题,使用了一张细节纹理,当近看时混合地形纹理。细节纹理没有被拉伸,消除了近看模糊问题。
地形被分成一个地形小块表格。地形小块可能在不同的细节层次被场景管理器显示出来,依赖于小块的布局和离观察者的距离。整个地形被投射到一个世界坐标空间中,在里面地形的尺寸。
目录
Configuration Parameters
地形场景管理器通过terrain.cfg教本被设置。
Basic Configuration Parameters
1. WorldTexture: 指定地形纹理的名称。
2. DetailTexture: 指定细节纹理的名称。
3. DetailTile: 这个指定细节纹理在每个地形小块中重复次数,也就是说,如果这个值是n,细节纹理将在每个地形小块的n*n格中被显示。如果这个值设置过低,地形在近看时会模糊,反之则会在放眼观察时看起来有反复模式(露馅了,^_^) 。
4. PageSource: 指定高度图数据的来源,默认为Heightmap.
5. Heightmap.image: 指定高度图的名称。尺寸必须是方形,而且要符合2^n+1, 高度图越大,地形细节就越高,但是程序消耗的的资源也越多(包括程序启动时间)。
6. PageSize: 地形将会有PageSize * PageSize那么大。如上所述,必须要符合2^n+1 (如65,129,257,513,1025)。
7. TileSize: 地形小块有 TileSize * TileSize大小。这个数必须小于PageSize。这个数必须要符合2^n+1须要符合2^n+1。设的过小会严重影响性能,太大的话又会在场景的某些部分导致不必要的高细节。
8. MaxPixelError: 指定当决定哪个细节层次被使用时的最大允许误差。设置过高会导致地形撕裂,过低则会影响性能。
9. PageWorldX, PageWorldZ: 设定地形在世界坐标系中的范围,地形越大,细节越低,地形使用的顶点数基于高度图,不是世界大小,你可以缩放地形到你想要的任意大小。
10. MaxHeight: 在世界坐标系中地形的最大高度。高度图中的0..255 缩放到世界坐标系中的 0..MaxHeight。
11. MaxMipMapLevel: 指定渲染地形使用的细节层次的数目。地形的远处和平坦处会以低细节渲染。
Advanced Configuration Parameters
有些高度图保存为raw格式,下列参数描述raw格式。
12. Heightmap.raw.size: 指定高度图的尺寸,要求同上。
13. Heightmap.raw.bpp: 指定每象素字节数,1=8 bits, 2=16 bits。
14. Heightmap.flip: 如果设置为true,则翻转高度图。
高度图处理说明
高度图必须是灰度图,如果不是,可以使用photoshop处理,选择菜单【图像】->模式->灰度,然后存为png格式即可。
坐标系问题
Terrain Scene Manager把纹理图的左上角作为世界原点(0,0,0),以从左到右为x正方向,从上到下为z正方向,从屏幕里到屏幕外为y正方向,符合右手坐标系。
posted @
2006-11-29 00:22 gogoplayer 阅读(1281) |
评论 (0) |
编辑 收藏