一个Delta3d程序启动过程详解
一、初始化一个dtGame::GameApplication的实例,dtGame::GameApplication* app = new dtGame::GameApplication();
设置游戏库的名称,SetGameLibraryName("libname");
调用app->Config("config.xml");Config内容如下:
//解析GameEntryPoint的dll,获取相关函数指针
dtUtil::LibrarySharingManager& lsm = dtUtil::LibrarySharingManager::GetInstance();
std::string libName = GetGameLibraryName();
mEntryPointLib = lsm.LoadSharedLibrary(libName);
dtUtil::LibrarySharingManager::LibraryHandle::SYMBOL_ADDRESS createAddr;
dtUtil::LibrarySharingManager::LibraryHandle::SYMBOL_ADDRESS destroyAddr;
createAddr = mEntryPointLib->FindSymbol("CreateGameEntryPoint");
destroyAddr = mEntryPointLib->FindSymbol("DestroyGameEntryPoint");
mCreateFunction = reinterpret_cast<CreateEntryPointFn>(createAddr);
mDestroyFunction = reinterpret_cast<DestroyEntryPointFn>(destroyAddr);
//创建Aplication和GameManager
mApplication = mEntryPoint->CreateApplication(configFileName);
mGameManager = new dtGame::GameManager(*mApplication->GetScene());
//执行相关初始化
mEntryPoint->Initialize(*mApplication, mArgc, mArgv);
mApplication->Config();
mEntryPoint->OnStartup(*mApplication, *mGameManager);
//开始系统循环
dtCore::System::GetInstance().Start();
在GameEntryPoint中的OnStartUp函数中将相应的组件添加至游戏管理器GameManager中;
在dtCore::System中有一个定时的循环,在循环中发送相关的消息(System::MESSAGE_FRAME等),然后在dtABC::BaseABC中的OnMessage()中进行消息响应。
void BaseABC::OnMessage(MessageData* data)
{
if (data->message == dtCore::System::MESSAGE_EVENT_TRAVERSAL)
{
EventTraversal(*static_cast<const double*>(data->userData));
}
else if (data->message == dtCore::System::MESSAGE_PRE_FRAME)
{
PreFrame(*static_cast<const double*>(data->userData));
}
else if (data->message == dtCore::System::MESSAGE_FRAME)
{
Frame(*static_cast<const double*>(data->userData));
}
else if (data->message == dtCore::System::MESSAGE_POST_FRAME)
{
PostFrame(*static_cast<const double*>(data->userData));
}
else if (data->message == dtCore::System::MESSAGE_PAUSE)
{
Pause(*static_cast<const double*>(data->userData));
}
}
在Frame函数中进行模型的渲染
void Application::Frame(const double deltaSimTime)
{
if(!mCompositeViewer->done())
{
bool singleThreaded = mCompositeViewer->getThreadingModel() == osgViewer::ViewerBase::SingleThreaded;
//NOTE: The OSG frame() advances the clock and does three traversals, event, update, and render.
//We are moving the event traversal to be its own message so we can reliably accept input during the
//typical Delta3D update of PreFrame(). The only exception to this is that we need
if(mFirstFrame)
{
#ifndef MULTITHREAD_FIX_HACK_BREAKS_CEGUI
dtCore::ObserverPtr<osgViewer::GraphicsWindow> gw;
if (GetWindow() != NULL)
{
gw = GetWindow()->GetOsgViewerGraphicsWindow();
}
if (!singleThreaded && gw.valid() && gw->isRealized())
{
gw->releaseContext();
}
#endif
if (singleThreaded) { GetCompositeViewer()->setReleaseContextAtEndOfFrameHint(false); }
mCompositeViewer->setUpThreading();
mCompositeViewer->frame(dtCore::System::GetInstance().GetSimTimeSinceStartup());
mFirstFrame = false;
}
// NOTE: The new version OSG (2.2) relies on absolute frame time
// to update drawables; especially particle systems.
// The time delta will be ignored here and the absolute simulation
// time passed to the OSG scene updater.
mCompositeViewer->advance(dtCore::System::GetInstance().GetSimTimeSinceStartup());
mCompositeViewer->updateTraversal();
mCompositeViewer->renderingTraversals();
}
}