Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,440 @@
|
||||
#include "mainloop.h"
|
||||
|
||||
#include "iconcomponent.h"
|
||||
#include "modelsplittercomponent.h"
|
||||
#include "motionmodel.h"
|
||||
#include "orthomotionmodel.h"
|
||||
#include "playercomponent.h"
|
||||
#include "roomdestructioncomponent.h"
|
||||
#include "textcomponent.h"
|
||||
#include "viewerinterfaceimpl.h"
|
||||
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/init.h>
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <dtEntity/profile.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/systeminterface.h>
|
||||
#include <dtEntity/entitymanager.h>
|
||||
#include <dtEntityOSG/initosgviewer.h>
|
||||
#include <dtEntityOSG/layerattachpointcomponent.h>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/lightcomponent.h>
|
||||
#include <dtEntityOSG/cameracomponent.h>
|
||||
#include <dtEntityOSG/osgsysteminterface.h>
|
||||
#include <dtEntityOSG/osgwindowinterface.h>
|
||||
#include <dtEntityOSG/osgdebugdrawinterface.h>
|
||||
#include <dtEntityOSG/osginputinterface.h>
|
||||
#include <dtEntityOSG/positionattitudetransformcomponent.h>
|
||||
#include <dtEntityOSG/staticmeshcomponent.h>
|
||||
#include <osgDB/Registry>
|
||||
#include <osgViewer/CompositeViewer>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
|
||||
#ifdef BUILD_WITH_GSTREAMER
|
||||
#include "videocomponent.h"
|
||||
#endif
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class MyReadFileCallback : public osgDB::Registry::ReadFileCallback
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual osgDB::ReaderWriter::ReadResult readNode(const std::string &fileName, const osgDB::ReaderWriter::Options *options)
|
||||
{
|
||||
osgDB::ReaderWriter::ReadResult res = osgDB::Registry::instance()->readNodeImplementation(fileName, options);
|
||||
if (res.notFound() || res.notHandled() || res.error())
|
||||
{
|
||||
LOG_DEBUG("DatabasePager could not load file, stopped trying: " << fileName);
|
||||
return osgDB::ReaderWriter::ReadResult(nullptr, osgDB::ReaderWriter::ReadResult::FILE_LOADED);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class MainLoop::Impl
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
osg::ref_ptr<osgViewer::CompositeViewer> mViewer;
|
||||
CtrlImpl *mInterface = nullptr;
|
||||
dtEntityOSG::OSGSystemInterface *mSysIf = nullptr;
|
||||
dtEntityOSG::OSGInputInterface *mInputIf = nullptr;
|
||||
dtEntity::EntityManager *mEntityManager;
|
||||
osg::Timer_t mStartFrameTick = 0;
|
||||
dtEntity::Timer_t mSimulationClockTime = 0;
|
||||
bool mProfilingEnabled = false;
|
||||
|
||||
Impl()
|
||||
: mEntityManager(new dtEntity::EntityManager)
|
||||
{
|
||||
dtEntity::MessageFunctor f(this, &MainLoop::Impl::onFastForward);
|
||||
mEntityManager->RegisterForMessages(dtEntity::SID("FastForwardMessage"), f);
|
||||
|
||||
dtEntity::MessageFunctor s(this, &MainLoop::Impl::onEntitySelected);
|
||||
mEntityManager->RegisterForMessages(dtEntity::RequestEntitySelectMessage::TYPE, s);
|
||||
|
||||
dtEntity::MessageFunctor s2(this, &MainLoop::Impl::onEntityDeselected);
|
||||
mEntityManager->RegisterForMessages(dtEntity::RequestEntityDeselectMessage::TYPE, s2);
|
||||
}
|
||||
|
||||
~Impl()
|
||||
{
|
||||
delete mEntityManager;
|
||||
delete mSysIf;
|
||||
delete mInputIf;
|
||||
delete mInterface;
|
||||
}
|
||||
|
||||
// react to fast forward message by
|
||||
void onFastForward(const dtEntity::Message &msg)
|
||||
{
|
||||
// TODO Test!
|
||||
double endtime = msg.GetDouble(dtEntity::SID("EndTime"));
|
||||
|
||||
while (mInterface->GetSimulationTime() < endtime)
|
||||
{
|
||||
constexpr auto step = 0.5;
|
||||
double t = mInterface->GetSimulationTime() + step;
|
||||
mSimulationClockTime += step / osg::Timer::instance()->getSecondsPerTick();
|
||||
mInterface->SetSimulationTime(t);
|
||||
mSysIf->SetTimeValues(t, step, step, mSimulationClockTime);
|
||||
mViewer->advance(t);
|
||||
mViewer->eventTraversal();
|
||||
mSysIf->EmitTickMessagesAndQueuedMessages();
|
||||
mViewer->updateTraversal();
|
||||
mSysIf->EmitPostUpdateMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// translate RequestEntitySelectMessage to EntityDeselectedMessage
|
||||
// (normally this would be handled by a selection manager, but
|
||||
// selection in this viewer is so simple that it is not necessary
|
||||
// to have real selection management)
|
||||
void onEntitySelected(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::RequestEntitySelectMessage &msg =
|
||||
static_cast<const dtEntity::RequestEntitySelectMessage &>(m);
|
||||
dtEntity::EntitySelectedMessage mo;
|
||||
mo.SetAboutEntityId(msg.GetAboutEntityId());
|
||||
mEntityManager->EmitMessage(mo);
|
||||
}
|
||||
|
||||
// translate RequestEntityDeselectMessage to EntityDeselectedMessage
|
||||
void onEntityDeselected(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::RequestEntityDeselectMessage &msg =
|
||||
static_cast<const dtEntity::RequestEntityDeselectMessage &>(m);
|
||||
dtEntity::EntityDeselectedMessage mo;
|
||||
mo.SetAboutEntityId(msg.GetAboutEntityId());
|
||||
mEntityManager->EmitMessage(mo);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
MainLoop::MainLoop(int argc, char **argv, QWidget *parentWidget)
|
||||
: mImpl(new Impl)
|
||||
{
|
||||
osgDB::Registry::instance()->setReadFileCallback(new MyReadFileCallback());
|
||||
|
||||
assert(!mImpl->mViewer.valid());
|
||||
|
||||
//////////////////////////// Setup OSG Viewer /////////////////////////
|
||||
// osg arguments parser wants to modify argc, argv
|
||||
{
|
||||
int argc_cpy = argc;
|
||||
std::vector<char *> argv_cpy;
|
||||
argv_cpy.reserve(argc);
|
||||
for (int i = 0; i < argc; ++i)
|
||||
argv_cpy.push_back(argv[i]);
|
||||
osg::ArgumentParser args(&argc_cpy, argv_cpy.data());
|
||||
|
||||
#ifdef _MSC_VER
|
||||
_putenv_s("OSG_RUN_FRAME_SCHEME", "ON_DEMAND");
|
||||
#else
|
||||
setenv("OSG_RUN_FRAME_SCHEME", "ON_DEMAND", 1);
|
||||
#endif
|
||||
// turn on antialiasing
|
||||
osg::DisplaySettings::instance()->setNumMultiSamples(4);
|
||||
osg::DisplaySettings::instance()->setDepthBuffer(true);
|
||||
|
||||
|
||||
mImpl->mViewer = new osgViewer::CompositeViewer(args);
|
||||
// Qt5 is currently crashing and reporting "Cannot make QOpenGLContext current in a different
|
||||
// thread" when the viewer is run multi-threaded, this is regression from Qt4
|
||||
mImpl->mViewer->setThreadingModel(osgViewer::CompositeViewer::SingleThreaded);
|
||||
|
||||
// don't exit on escape
|
||||
mImpl->mViewer->setKeyEventSetsDone(0);
|
||||
|
||||
//mImpl->mViewer->setEndBarrierPosition(osgViewer::ViewerBase::BeforeSwapBuffers);
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
dtEntity::LogManager::GetInstance().AddListener(new dtEntity::ConsoleLogHandler());
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////// setup dtEntity -> OSG interfaces ////////////////////////
|
||||
{
|
||||
mImpl->mSysIf = new dtEntityOSG::OSGSystemInterface(mImpl->mEntityManager->GetMessagePump(), argc, (const char **)argv);
|
||||
mImpl->mInputIf = new dtEntityOSG::OSGInputInterface(mImpl->mEntityManager->GetMessagePump());
|
||||
// give application system access to viewer
|
||||
mImpl->mSysIf->SetViewer(mImpl->mViewer);
|
||||
dtEntity::SetSystemInterface(mImpl->mSysIf);
|
||||
dtEntity::SetInputInterface(mImpl->mInputIf);
|
||||
dtEntity::SetWindowInterface(new dtEntityOSG::OSGWindowInterface(*mImpl->mEntityManager));
|
||||
|
||||
dtEntity::SetupDataPaths(argc, argv, false);
|
||||
}
|
||||
|
||||
|
||||
dtEntity::EntityManager &em = *mImpl->mEntityManager;
|
||||
|
||||
//////////////////////////// Add entity systems /////////////////////////
|
||||
{
|
||||
// this is a required component system, so add it immediately
|
||||
em.AddEntitySystem(*new dtEntity::MapSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::LayerSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::CameraSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::PositionAttitudeTransformSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::StaticMeshSystem(em));
|
||||
em.AddEntitySystem(*new RoomDestructionSystem(em));
|
||||
em.AddEntitySystem(*new MotionModelSystem(em));
|
||||
em.AddEntitySystem(*new ModelSplitterSystem(em));
|
||||
em.AddEntitySystem(*new OrthoMotionModelSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::LightSystem(em));
|
||||
em.AddEntitySystem(*new PlayerSystem(em));
|
||||
em.AddEntitySystem(*new IconSystem(em));
|
||||
em.AddEntitySystem(*new TextSystem(em));
|
||||
#ifdef BUILD_WITH_GSTREAMER
|
||||
em.AddEntitySystem(*new VideoSystem(em));
|
||||
#endif
|
||||
|
||||
dtEntityOSG::LayerAttachPointSystem *layerattach = new dtEntityOSG::LayerAttachPointSystem(em);
|
||||
em.AddEntitySystem(*layerattach);
|
||||
layerattach->CreateSceneGraphRootEntity(new osg::Group());
|
||||
|
||||
mImpl->mInterface = new CtrlImpl(em, parentWidget);
|
||||
|
||||
// need layer system for debug draw interface, so set it up now
|
||||
dtEntity::SetDebugDrawInterface(new dtEntityOSG::OSGDebugDrawInterface(em));
|
||||
}
|
||||
|
||||
//////////////////////////// Init time tracking /////////////////////////
|
||||
{
|
||||
mImpl->mStartFrameTick = osg::Timer::instance()->tick();
|
||||
mImpl->mInterface->SetSimulationTime(0);
|
||||
time_t t;
|
||||
time(&t);
|
||||
mImpl->mSimulationClockTime = t / osg::Timer::instance()->getSecondsPerTick();
|
||||
}
|
||||
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string curArgv = argv[i];
|
||||
if (!curArgv.empty() && curArgv == "--openOverview")
|
||||
mImpl->mInterface->OpenOverview();
|
||||
}
|
||||
|
||||
//////////////////////////// Start simulation /////////////////////////
|
||||
{
|
||||
dtEntity::StartSystemMessage msg;
|
||||
em.EnqueueMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
MainLoop::~MainLoop()
|
||||
{
|
||||
delete mImpl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::EntityManager *MainLoop::getEntityManager() const
|
||||
{
|
||||
return mImpl->mEntityManager;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ViewerInterface *MainLoop::getViewerInterface() const
|
||||
{
|
||||
return mImpl->mInterface;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool MainLoop::getProfilingEnabled() const
|
||||
{
|
||||
return mImpl->mProfilingEnabled;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void MainLoop::setProfilingEnabled(bool v)
|
||||
{
|
||||
mImpl->mProfilingEnabled = v;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void MainLoop::tick()
|
||||
{
|
||||
dtEntityOSG::OSGSystemInterface *iface = dtEntityOSG::GetOSGSystemInterface();
|
||||
|
||||
if (!mImpl->mInterface->allViewWindowsExposed())
|
||||
return;
|
||||
|
||||
if (getViewerInterface()->GetNonRealtimeMode())
|
||||
{
|
||||
float deltaTime = 1.0f / mImpl->mInterface->GetFrameRate();
|
||||
float deltaSimTime = deltaTime;
|
||||
mImpl->mSimulationClockTime += deltaSimTime / osg::Timer::instance()->getSecondsPerTick();
|
||||
mImpl->mInterface->SetSimulationTime(mImpl->mInterface->GetSimulationTime() + deltaSimTime);
|
||||
iface->SetTimeValues(mImpl->mInterface->GetSimulationTime(), deltaSimTime, deltaTime, mImpl->mSimulationClockTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
float deltaTime = 0;
|
||||
float deltaSimTime = 0;
|
||||
|
||||
dtEntity::Timer_t tick = osg::Timer::instance()->tick();
|
||||
deltaTime = static_cast<float>(osg::Timer::instance()->delta_s(mImpl->mStartFrameTick, tick));
|
||||
deltaSimTime = deltaTime * mImpl->mInterface->GetTimeScale();
|
||||
mImpl->mStartFrameTick = tick;
|
||||
|
||||
mImpl->mSimulationClockTime += deltaSimTime / osg::Timer::instance()->getSecondsPerTick();
|
||||
mImpl->mInterface->SetSimulationTime(mImpl->mInterface->GetSimulationTime() + deltaSimTime);
|
||||
iface->SetTimeValues(mImpl->mInterface->GetSimulationTime(), deltaSimTime, deltaTime, mImpl->mSimulationClockTime);
|
||||
}
|
||||
|
||||
if (mImpl->mProfilingEnabled)
|
||||
{
|
||||
|
||||
static dtEntity::StringId frameId = dtEntity::SID("Frame");
|
||||
static dtEntity::StringId frameAdvanceId = dtEntity::SID("Frame_Advance");
|
||||
static dtEntity::StringId frameEvTrId = dtEntity::SID("Frame_EventTraversal");
|
||||
static dtEntity::StringId frameUpTrId = dtEntity::SID("Frame_UpdateTraversal");
|
||||
static dtEntity::StringId frameRenderTrId = dtEntity::SID("Frame_RenderingTraversals");
|
||||
|
||||
static unsigned int framecount = 0;
|
||||
|
||||
CProfileManager::Increment_Frame_Counter();
|
||||
|
||||
CProfileManager::Start_Profile(frameId);
|
||||
|
||||
CProfileManager::Start_Profile(frameAdvanceId);
|
||||
mImpl->mViewer->advance();
|
||||
CProfileManager::Stop_Profile();
|
||||
|
||||
CProfileManager::Start_Profile(frameEvTrId);
|
||||
mImpl->mViewer->eventTraversal();
|
||||
iface->EmitTickMessagesAndQueuedMessages();
|
||||
|
||||
CProfileManager::Stop_Profile();
|
||||
|
||||
if (mImpl->mViewer->getNumViews() > 0 && mImpl->mViewer->checkNeedToDoFrame())
|
||||
{
|
||||
CProfileManager::Start_Profile(frameUpTrId);
|
||||
mImpl->mViewer->updateTraversal();
|
||||
iface->EmitPostUpdateMessage();
|
||||
CProfileManager::Stop_Profile();
|
||||
|
||||
CProfileManager::Start_Profile(frameRenderTrId);
|
||||
mImpl->mViewer->renderingTraversals();
|
||||
CProfileManager::Stop_Profile();
|
||||
}
|
||||
else
|
||||
iface->EmitPostUpdateMessage();
|
||||
|
||||
CProfileManager::Stop_Profile(); // frameId
|
||||
|
||||
if (++framecount > 99)
|
||||
{
|
||||
CProfileManager::dumpAll();
|
||||
fflush(stdout);
|
||||
framecount = 0;
|
||||
CProfileManager::Reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
NASTY BUG WORKAROUND:
|
||||
Somehow, changes made to the frame are not immediately shown when
|
||||
a new frame is requested. This only happens when more than one view is opened.
|
||||
The workaround is to render again two more times even if no frame redraw
|
||||
was requested.
|
||||
*/
|
||||
static int renderagaincnt = 0;
|
||||
|
||||
mImpl->mViewer->advance(DBL_MAX);
|
||||
mImpl->mViewer->eventTraversal();
|
||||
iface->EmitTickMessagesAndQueuedMessages();
|
||||
bool needFrame = mImpl->mViewer->checkNeedToDoFrame();
|
||||
if (mImpl->mViewer->getNumViews() > 0 && (renderagaincnt != 0 || needFrame))
|
||||
{
|
||||
if (mImpl->mViewer->getNumViews() == 1)
|
||||
renderagaincnt = 0;
|
||||
else if (needFrame)
|
||||
renderagaincnt = 2;
|
||||
else
|
||||
--renderagaincnt;
|
||||
|
||||
mImpl->mViewer->updateTraversal();
|
||||
iface->EmitPostUpdateMessage();
|
||||
mImpl->mViewer->renderingTraversals();
|
||||
}
|
||||
else
|
||||
iface->EmitPostUpdateMessage();
|
||||
}
|
||||
|
||||
if (!getViewerInterface()->GetNonRealtimeMode() && mImpl->mViewer->getRunMaxFrameRate() > 0.0)
|
||||
{
|
||||
if (mImpl->mProfilingEnabled)
|
||||
{
|
||||
static dtEntity::StringId sleepId = dtEntity::SID("Frame_Sleep");
|
||||
CProfileManager::Start_Profile(sleepId);
|
||||
}
|
||||
osg::Timer_t endFrameTick = osg::Timer::instance()->tick();
|
||||
double frameTime =
|
||||
osg::Timer::instance()->delta_s(mImpl->mStartFrameTick, endFrameTick);
|
||||
|
||||
double minFrameTime = 1.0 / mImpl->mViewer->getRunMaxFrameRate();
|
||||
if (frameTime < minFrameTime)
|
||||
OpenThreads::Thread::microSleep(1000000.0 * (minFrameTime - frameTime));
|
||||
if (mImpl->mProfilingEnabled)
|
||||
CProfileManager::Stop_Profile();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void MainLoop::GetCurrentPosition(Vec3d &position, Vec3d &lookAt)
|
||||
{
|
||||
position = Vec3d();
|
||||
lookAt = Vec3d();
|
||||
dtEntity::MapSystem *ms;
|
||||
mImpl->mEntityManager->GetES(ms);
|
||||
if (!ms)
|
||||
return;
|
||||
dtEntity::EntityId eid = ms->GetEntityIdByUniqueId("cam_overview");
|
||||
dtEntityOSG::CameraComponent *camcomp;
|
||||
if (!mImpl->mEntityManager->GetComponent(eid, camcomp))
|
||||
{
|
||||
LOG_ERROR("GetCurrentPosition: Error accessing camera");
|
||||
return;
|
||||
}
|
||||
|
||||
osg::Vec3d p = camcomp->GetPosition();
|
||||
osg::Vec3d la = camcomp->GetEyeDirection() + camcomp->GetPosition();
|
||||
position.x = p[0]; position.y = p[1]; position.z = p[2];
|
||||
lookAt.x = la[0]; lookAt.y = la[1]; lookAt.z = la[2];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user