ogre 学习笔记 - Day 4
由于电脑C盘硬盘坏了,重新买了硬盘,重装系统,耽误了两天。
先回顾之前SampleBrowser的学习, 回忆一下。
SamplerBrowser加载了一些Sample资源,然后生成UI,通过点击选择Sample。 这里就出现了3个点
UI属于组件,暂时不管它。先看加载资源以及加载场景。
资源加载
Sample* loadSamples()
{
Ogre::ConfigFile cfg;
#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
#else
cfg.load(mFSLayer->getConfigFilePath("samples.cfg"));
#endif
}
只看 Windows部分,首先,通过FileSystemLayer::getConfigFilePath 加载了一个配置文件。但是这个配置文件只有一个名称,它存放在哪呢? 通过vscode ctrl+p 查找文件,发现好多个。都打开看一下,发现都是一样的内容.
SampleFolder=.
SamplePlugin=DefaultSamples
#SamplePlugin=PlayPenTests
这个格式很像 .ini [key=value]. 根据名称猜测,SampleFolder=. 是说Sample的文件夹在应用同级目录。SamplePlugin 不知道是什么意思。
问题来了,只有一个名字,怎么知道是哪个呢?
Ogre::String getConfigFilePath(Ogre::String filename) const
{
Ogre::String path = getWritablePath(filename);
if (fileExists(path))
return path;
for (const String& cpath : mConfigPaths)
{
path = cpath + filename;
if (fileExists(path))
return path;
}
return filename;
}
首先,寻找可写路径
Ogre::String getWritablePath(const Ogre::String& filename) const
{
return mHomePath + filename;
}
出现了一个 mHomePath ,调试发现,它是一个不存在的路径。
然后,找 configPaths。
看看 homepath,configpath是如何赋值的。
-
HomePath void setHomePath(const Ogre::String &path){
mHomePath = path;
}
一眼看见 setHomePath函数,调试竟然没运行到!无奈,全局搜索吧。 void FileSystemLayer::prepareUserHome(const Ogre::String& subdir)
{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
WCHAR wpath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL, 0, wpath)))
widePathToOgreString(mHomePath, wpath);
#elif OGRE_PLATFORM == OGRE_PLATFORM_WINRT
widePathToOgreString(mHomePath, Windows::Storage::ApplicationData::Current->LocalFolder->Path->Data());
#endif
if(!mHomePath.empty())
{
mHomePath += '\\' + subdir + '\\';
if (!createDirectory(mHomePath))
{
mHomePath.clear();
}
}
}
FileSystemLayer(const Ogre::String& subdir)
{
getConfigPaths();
prepareUserHome(subdir);
}
ApplicationContextBase::ApplicationContextBase(const Ogre::String& appName)
{
mAppName = appName;
mFSLayer = new Ogre::FileSystemLayer(mAppName);
}
hOME PATH 通过 SHGetFolderPathW(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE,…)拿到用户的文档路径,然后加上应用的名,组成的路径。例如:C:/Users/xxx/Documents/SampleBrowser/ -
configPaths void FileSystemLayer::getConfigPaths()
{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
String appPath = getModulePath(false);
#elif OGRE_PLATFORM == OGRE_PLATFORM_WINRT
Ogre::String appPath;
widePathToOgreString(appPath, Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data());
#endif
if (!appPath.empty())
mConfigPaths.push_back(appPath + '\\');
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
mConfigPaths.push_back(StringUtil::normalizeFilePath(getModulePath(true)+"/../../../bin/"));
#endif
}
-
应用所在路径(SampleBrowser的路径) -
dll所在的路径 按照这个思路,就能找到真正使用的samples.cfg了。 路径是按照顺序查找的,那么当文件重名时,就容易找错了。
读取配置文件内容
Ogre::String sampleDir = cfg.getSetting("SampleFolder");
Ogre::StringVector sampleList = cfg.getMultiSetting("SamplePlugin");
Ogre::String startupSampleTitle = cfg.getSetting("StartupSample");
for (Ogre::StringVector::iterator i = sampleList.begin(); i != sampleList.end(); i++)
{
try
{
#ifdef OGRE_STATIC_LIB
#else
mRoot->loadPlugin(sampleDir + *i);
#endif
}
catch (Ogre::Exception& e)
{
Ogre::LogManager::getSingleton().logError(e.what());
unloadedSamplePlugins.push_back(sampleDir + *i);
continue;
}
}
读取数据之后,发现,配置中的SamplePlugin=DefaultSamples,竟然通过loadPlugin的方式加载,也就是说它把sample当成了插件!按照它的plugin的操作,按照名称导入DLL。所以,按名称找到工程当中的DefaultSamples. 就是它了。打开DefaultSamples,发现所有sample的代码。
既然把Sample当成了插件,那就不需要再深入探究了。回过头看如何加载场景。
场景加载
要加载场景,必然要new 场景对象,在sample的构造函数里下个断点。运行场景函数 runSamle下一个断点。运行发现
DefaultSamplesPlugin::DefaultSamplesPlugin() : SamplePlugin("DefaultSamplesPlugin")
{
addSample(new Sample_AtomicCounters);
addSample(new Sample_BezierPatch);
}
加载插件时,new了很多场景
任选一个场景,点击start。进入 runSample.
virtual void runSample(Sample* s)
{
s->_setup(mWindow, mFSLayer, mOverlaySystem);
}
virtual void _setup(Ogre::RenderWindow* window, Ogre::FileSystemLayer* fsLayer, Ogre::OverlaySystem* overlaySys)
{
Sample::_setup(window, fsLayer, overlaySys);
if(mTrayMgr)
mControls.reset(new AdvancedRenderControls(mTrayMgr.get(), mCamera));
}
virtual void _setup(Ogre::RenderWindow* window, Ogre::FileSystemLayer* fsLayer, Ogre::OverlaySystem* overlaySys)
{
mOverlaySystem = overlaySys;
mWindow = window;
mFSLayer = fsLayer;
locateResources();
createSceneManager();
setupView();
mCameraMan.reset(new CameraMan(mCameraNode));
loadResources();
mResourcesLoaded = true;
setupContent();
mContentSetup = true;
mDone = false;
}
void loadResources()
{
mTrayMgr->showLoadingBar(1, 1, 0);
ResourceGroupManager& rgm = ResourceGroupManager::getSingleton();
rgm.setCustomStagesForResourceGroup("BSPWorld", mSceneMgr->estimateWorldGeometry("maps/oa_rpg3dm2.bsp"));
rgm.initialiseResourceGroup("BSPWorld");
rgm.loadResourceGroup("BSPWorld");
mSceneMgr->setWorldGeometry("maps/oa_rpg3dm2.bsp");
mTrayMgr->hideLoadingBar();
}
与前几天所知的一样,在 setup里,最终进入 loadResources(),setupContent()。 找到了sample的创建/加载/运行的方法,就可以对每一个sample分别进行学习了。
|