CompositeViewer: Support for multiple view windows using osgViewer::CompositeViewer.
Overview: Previously Flightgear always used a single osgViewer::Viewer(), which inherits from both osgViewer::ViewerBase and osgViewer::View, giving a single view window. If CompositeViewer is enabled, we instead use a osgViewer::CompositeViewer which contains a list of osgViewer::View's. Each of these View's can have its own eye position, so we can have multiple different views of the same scene. Enable at runtime with: --composite-viewer=1 Changes to allow use of osgViewer::CompositeViewer: Previously FGRenderer had this method: osgViewer::Viewer* getViewer(); This has been replaced by these two new methods: osgViewer::ViewerBase* getViewerBase(); osgViewer::View* getView(); If CompositeViewer is not enabled (the default), the actual runtime state is unchanged, and getViewerBase() and getView() both return a pointer to the singleton osgViewer::Viewer() object. If CompositeViewer is enabled, getViewerBase() returns a pointer to a singleton osgViewer::CompositeViewer object, and getView() returns a pointer to the first osgViewer::View in the osgViewer::CompositeViewer's list. The other significant change to FGRenderer() is the new method: osg::FrameStamp* getFrameStamp() If CompositeViewer is not enabled, this simply returns getView()->getFrameStamp(). If CompositeViewer is enabled it returns getViewerBase()->getFrameStamp(). It is important that code that previously called getView()->getFrameStamp() is changed to use the new method, because when CompositeViewer is enabled individual osgViewer::View's appear to return an osg::FrameStamp with zero frame number). All code that uses FGRenderer has been patched up to use the new methods so that things work as before regardless of whether CompositeViewer is enabled or not. We make FGRenderer::update() call SviewUpdate() which updates any extra views. Extra view windows: If CompositeViewer is enabled, one can create top-level extra view windows by calling SviewCreate(). See src/Viewer/sview.hxx for details. Each extra view window has its own simgear::compositor::Compositor instance. Currently SviewCreate() can create extra view windows that clone the current view, or view from one point to another (e.g. from one multiplayer aircraft to the user's aircradt) or keep two aircraft in view, one at a fixed distance in the foreground. SviewCreate() can be called from nasal via new nasal commands "view-clone", "view-last-pair", "view-last-pair-double" and "view-push". Associated changes to fgdata gives access to these via the View menu. The "view-push" command tags the current view for later use by "view-last-pair" and "view-last-pair-double". Extra view windows created by SviewCreate() use a new view system called Sview, which allows views to be constructed at runtime instead of being hard-coded in *-set.xml files. This is work in progress and views aren't all fully implemented. For example Pilot view gets things slightly wrong with large roll values, Tower View AGL is not implemented, and we don't implement damping. See top of src/Viewer/sview.cxx for an overview. OpenSceneGraph-3.4 issues: OSG-3.4's event handling seems to be incorrect with CompositeViewer - events get sent for the wrong window which causes issues with resize and closing. It doesn't seem to be possible to work around this, so closing extra view windows can end up closing the main window for example. OSG-3.6 seems to fix the problems. We warn if CompositeViewer is enabled and OpenSceneGraph is 3.4.
This commit is contained in:
parent
578f414c42
commit
f62e5b9ce3
31 changed files with 1972 additions and 172 deletions
|
@ -672,7 +672,7 @@ void GUIMgr::init()
|
||||||
|
|
||||||
_event_handler = new GUIEventHandler(desktop);
|
_event_handler = new GUIEventHandler(desktop);
|
||||||
globals->get_renderer()
|
globals->get_renderer()
|
||||||
->getViewer()
|
->getView()
|
||||||
->getEventHandlers()
|
->getEventHandlers()
|
||||||
// GUI is on top of everything so lets install as first event handler
|
// GUI is on top of everything so lets install as first event handler
|
||||||
.push_front( _event_handler );
|
.push_front( _event_handler );
|
||||||
|
@ -706,7 +706,7 @@ void GUIMgr::shutdown()
|
||||||
if( _event_handler )
|
if( _event_handler )
|
||||||
{
|
{
|
||||||
globals->get_renderer()
|
globals->get_renderer()
|
||||||
->getViewer()
|
->getView()
|
||||||
->removeEventHandler( _event_handler );
|
->removeEventHandler( _event_handler );
|
||||||
_event_handler = 0;
|
_event_handler = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ void CocoaFileDialog::exec()
|
||||||
// it window-modal.
|
// it window-modal.
|
||||||
NSWindow* cocoaWindow = nil;
|
NSWindow* cocoaWindow = nil;
|
||||||
std::vector<osgViewer::GraphicsWindow*> windows;
|
std::vector<osgViewer::GraphicsWindow*> windows;
|
||||||
globals->get_renderer()->getViewer()->getWindows(windows);
|
globals->get_renderer()->getViewerBase()->getWindows(windows);
|
||||||
|
|
||||||
for (auto gw : windows) {
|
for (auto gw : windows) {
|
||||||
// OSG doesn't use RTTI, so no dynamic cast. Let's check the class type
|
// OSG doesn't use RTTI, so no dynamic cast. Let's check the class type
|
||||||
|
|
|
@ -26,11 +26,11 @@ namespace {
|
||||||
HWND getMainViewerHWND()
|
HWND getMainViewerHWND()
|
||||||
{
|
{
|
||||||
osgViewer::Viewer::Windows windows;
|
osgViewer::Viewer::Windows windows;
|
||||||
if (!globals->get_renderer() || !globals->get_renderer()->getViewer()) {
|
if (!globals->get_renderer() || !globals->get_renderer()->getViewerBase()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
globals->get_renderer()->getViewer()->getWindows(windows);
|
globals->get_renderer()->getViewerBase()->getWindows(windows);
|
||||||
osgViewer::Viewer::Windows::const_iterator it = windows.begin();
|
osgViewer::Viewer::Windows::const_iterator it = windows.begin();
|
||||||
for(; it != windows.end(); ++it) {
|
for(; it != windows.end(); ++it) {
|
||||||
if (strcmp((*it)->className(), "GraphicsWindowWin32")) {
|
if (strcmp((*it)->className(), "GraphicsWindowWin32")) {
|
||||||
|
|
|
@ -61,11 +61,11 @@ bool isCanvasImplementationRegistered()
|
||||||
HWND getMainViewerHWND()
|
HWND getMainViewerHWND()
|
||||||
{
|
{
|
||||||
osgViewer::Viewer::Windows windows;
|
osgViewer::Viewer::Windows windows;
|
||||||
if (!globals || !globals->get_renderer() || !globals->get_renderer()->getViewer()) {
|
if (!globals || !globals->get_renderer() || !globals->get_renderer()->getViewerBase()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
globals->get_renderer()->getViewer()->getWindows(windows);
|
globals->get_renderer()->getViewerBase()->getWindows(windows);
|
||||||
osgViewer::Viewer::Windows::const_iterator it = windows.begin();
|
osgViewer::Viewer::Windows::const_iterator it = windows.begin();
|
||||||
for(; it != windows.end(); ++it) {
|
for(; it != windows.end(); ++it) {
|
||||||
if (strcmp((*it)->className(), "GraphicsWindowWin32")) {
|
if (strcmp((*it)->className(), "GraphicsWindowWin32")) {
|
||||||
|
|
|
@ -62,7 +62,7 @@ public:
|
||||||
{
|
{
|
||||||
mActualCursor = mCursor;
|
mActualCursor = mCursor;
|
||||||
|
|
||||||
globals->get_renderer()->getViewer()->getWindows(mWindows);
|
globals->get_renderer()->getViewerBase()->getWindows(mWindows);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setCursor(Cursor aCursor)
|
virtual void setCursor(Cursor aCursor)
|
||||||
|
@ -160,7 +160,7 @@ FGMouseCursor* FGMouseCursor::instance()
|
||||||
#ifdef SG_WINDOWS
|
#ifdef SG_WINDOWS
|
||||||
// set osgViewer cursor inherit, otherwise it will interefere
|
// set osgViewer cursor inherit, otherwise it will interefere
|
||||||
std::vector<osgViewer::GraphicsWindow*> gws;
|
std::vector<osgViewer::GraphicsWindow*> gws;
|
||||||
globals->get_renderer()->getViewer()->getWindows(gws);
|
globals->get_renderer()->getViewerBase()->getWindows(gws);
|
||||||
for (auto gw : gws) {
|
for (auto gw : gws) {
|
||||||
gw->setCursor(osgViewer::GraphicsWindow::InheritCursor);
|
gw->setCursor(osgViewer::GraphicsWindow::InheritCursor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,11 @@ namespace {
|
||||||
HWND getMainViewerHWND()
|
HWND getMainViewerHWND()
|
||||||
{
|
{
|
||||||
osgViewer::Viewer::Windows windows;
|
osgViewer::Viewer::Windows windows;
|
||||||
if (!globals->get_renderer() || !globals->get_renderer()->getViewer()) {
|
if (!globals->get_renderer() || !globals->get_renderer()->getViewerBase()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
globals->get_renderer()->getViewer()->getWindows(windows);
|
globals->get_renderer()->getViewerBase()->getWindows(windows);
|
||||||
osgViewer::Viewer::Windows::const_iterator it = windows.begin();
|
osgViewer::Viewer::Windows::const_iterator it = windows.begin();
|
||||||
for(; it != windows.end(); ++it) {
|
for(; it != windows.end(); ++it) {
|
||||||
if (strcmp((*it)->className(), "GraphicsWindowWin32")) {
|
if (strcmp((*it)->className(), "GraphicsWindowWin32")) {
|
||||||
|
|
|
@ -361,6 +361,54 @@ do_view_cycle (const SGPropertyNode * arg, SGPropertyNode * root)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Built-in command: view-push.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
do_view_push (const SGPropertyNode * arg, SGPropertyNode * root)
|
||||||
|
{
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "do_view_push() called");
|
||||||
|
globals->get_viewmgr()->view_push();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Built-in command: clone view.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
do_view_clone (const SGPropertyNode * arg, SGPropertyNode * root)
|
||||||
|
{
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "do_view_clone() called");
|
||||||
|
globals->get_viewmgr()->clone_current_view();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Built-in command: view last pair.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
do_view_last_pair (const SGPropertyNode * arg, SGPropertyNode * root)
|
||||||
|
{
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "do_view_last_pair() called");
|
||||||
|
globals->get_viewmgr()->clone_last_pair();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Built-in command: double view last pair.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
do_view_last_pair_double (const SGPropertyNode * arg, SGPropertyNode * root)
|
||||||
|
{
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "do_view_last_pair_double() called");
|
||||||
|
globals->get_viewmgr()->clone_last_pair_double();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Built-in command: toggle a bool property value.
|
* Built-in command: toggle a bool property value.
|
||||||
*
|
*
|
||||||
|
@ -948,6 +996,10 @@ static struct {
|
||||||
{ "save-tape", do_save_tape },
|
{ "save-tape", do_save_tape },
|
||||||
{ "load-tape", do_load_tape },
|
{ "load-tape", do_load_tape },
|
||||||
{ "view-cycle", do_view_cycle },
|
{ "view-cycle", do_view_cycle },
|
||||||
|
{ "view-push", do_view_push },
|
||||||
|
{ "view-clone", do_view_clone },
|
||||||
|
{ "view-last-pair", do_view_last_pair },
|
||||||
|
{ "view-last-pair-double", do_view_last_pair_double },
|
||||||
/*
|
/*
|
||||||
{ "set-sea-level-air-temp-degc", do_set_sea_level_degc },
|
{ "set-sea-level-air-temp-degc", do_set_sea_level_degc },
|
||||||
{ "set-outside-air-temp-degc", do_set_oat_degc },
|
{ "set-outside-air-temp-degc", do_set_oat_degc },
|
||||||
|
|
|
@ -1283,7 +1283,7 @@ void fgStartNewReset()
|
||||||
|
|
||||||
FGRenderer* render = globals->get_renderer();
|
FGRenderer* render = globals->get_renderer();
|
||||||
// needed or we crash in multi-threaded OSG mode
|
// needed or we crash in multi-threaded OSG mode
|
||||||
render->getViewer()->stopThreading();
|
render->getViewerBase()->stopThreading();
|
||||||
|
|
||||||
// order is important here since tile-manager shutdown needs to
|
// order is important here since tile-manager shutdown needs to
|
||||||
// access the scenery object
|
// access the scenery object
|
||||||
|
@ -1294,8 +1294,8 @@ void fgStartNewReset()
|
||||||
|
|
||||||
// don't cancel the pager until after shutdown, since AIModels (and
|
// don't cancel the pager until after shutdown, since AIModels (and
|
||||||
// potentially others) can queue delete requests on the pager.
|
// potentially others) can queue delete requests on the pager.
|
||||||
render->getViewer()->getDatabasePager()->cancel();
|
render->getView()->getDatabasePager()->cancel();
|
||||||
render->getViewer()->getDatabasePager()->clear();
|
render->getView()->getDatabasePager()->clear();
|
||||||
|
|
||||||
osgDB::Registry::instance()->clearObjectCache();
|
osgDB::Registry::instance()->clearObjectCache();
|
||||||
// Pager requests depend on this, so don't clear it until now
|
// Pager requests depend on this, so don't clear it until now
|
||||||
|
@ -1376,7 +1376,7 @@ void fgStartNewReset()
|
||||||
eventHandler->reset();
|
eventHandler->reset();
|
||||||
globals->set_renderer(render);
|
globals->set_renderer(render);
|
||||||
render->init();
|
render->init();
|
||||||
render->setViewer(viewer.get());
|
render->setView(viewer.get());
|
||||||
|
|
||||||
sgUserDataInit( globals->get_props() );
|
sgUserDataInit( globals->get_props() );
|
||||||
|
|
||||||
|
|
|
@ -195,15 +195,15 @@ FGGlobals::~FGGlobals()
|
||||||
// stop OSG threading first, to avoid thread races while we tear down
|
// stop OSG threading first, to avoid thread races while we tear down
|
||||||
// scene-graph pieces
|
// scene-graph pieces
|
||||||
// there are some scenarios where renderer is already gone.
|
// there are some scenarios where renderer is already gone.
|
||||||
osg::ref_ptr<osgViewer::Viewer> vw;
|
osg::ref_ptr<osgViewer::ViewerBase> vb;
|
||||||
if (renderer) {
|
if (renderer) {
|
||||||
vw = renderer->getViewer();
|
vb = renderer->getViewerBase();
|
||||||
if (vw) {
|
if (vb) {
|
||||||
// https://code.google.com/p/flightgear-bugs/issues/detail?id=1291
|
// https://code.google.com/p/flightgear-bugs/issues/detail?id=1291
|
||||||
// explicitly stop trheading before we delete the renderer or
|
// explicitly stop trheading before we delete the renderer or
|
||||||
// viewMgr (which ultimately holds refs to the CameraGroup, and
|
// viewMgr (which ultimately holds refs to the CameraGroup, and
|
||||||
// GraphicsContext)
|
// GraphicsContext)
|
||||||
vw->stopThreading();
|
vb->stopThreading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,9 +212,10 @@ FGGlobals::~FGGlobals()
|
||||||
|
|
||||||
// don't cancel the pager until after shutdown, since AIModels (and
|
// don't cancel the pager until after shutdown, since AIModels (and
|
||||||
// potentially others) can queue delete requests on the pager.
|
// potentially others) can queue delete requests on the pager.
|
||||||
if (vw && vw->getDatabasePager()) {
|
osgViewer::View* v = renderer->getView();
|
||||||
vw->getDatabasePager()->cancel();
|
if (v && v->getDatabasePager()) {
|
||||||
vw->getDatabasePager()->clear();
|
v->getDatabasePager()->cancel();
|
||||||
|
v->getDatabasePager()->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
osgDB::Registry::instance()->clearObjectCache();
|
osgDB::Registry::instance()->clearObjectCache();
|
||||||
|
@ -230,7 +231,7 @@ FGGlobals::~FGGlobals()
|
||||||
|
|
||||||
delete subsystem_mgr;
|
delete subsystem_mgr;
|
||||||
subsystem_mgr = nullptr; // important so ::get_subsystem returns NULL
|
subsystem_mgr = nullptr; // important so ::get_subsystem returns NULL
|
||||||
vw = nullptr;
|
vb = nullptr;
|
||||||
set_matlib(NULL);
|
set_matlib(NULL);
|
||||||
|
|
||||||
delete time_params;
|
delete time_params;
|
||||||
|
|
|
@ -743,10 +743,6 @@ int fgMainInit( int argc, char **argv )
|
||||||
fntInit();
|
fntInit();
|
||||||
globals->get_renderer()->preinit();
|
globals->get_renderer()->preinit();
|
||||||
|
|
||||||
#if defined(ENABLE_COMPOSITOR)
|
|
||||||
flightgear::addSentryTag("compositor", "yes");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fgGetBool("/sim/ati-viewport-hack", true)) {
|
if (fgGetBool("/sim/ati-viewport-hack", true)) {
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "Enabling ATI/AMD viewport hack");
|
SG_LOG(SG_GENERAL, SG_WARN, "Enabling ATI/AMD viewport hack");
|
||||||
flightgear::addSentryTag("ati-viewport-hack", "enabled");
|
flightgear::addSentryTag("ati-viewport-hack", "enabled");
|
||||||
|
|
|
@ -1617,6 +1617,7 @@ where:
|
||||||
OPTION_INT - property is an integer
|
OPTION_INT - property is an integer
|
||||||
OPTION_CHANNEL - name of option is the name of a channel
|
OPTION_CHANNEL - name of option is the name of a channel
|
||||||
OPTION_FUNC - the option trigger a function
|
OPTION_FUNC - the option trigger a function
|
||||||
|
property :
|
||||||
b_param : if type==OPTION_BOOL,
|
b_param : if type==OPTION_BOOL,
|
||||||
value set to the property (has_param is false for boolean)
|
value set to the property (has_param is false for boolean)
|
||||||
s_param : if type==OPTION_STRING,
|
s_param : if type==OPTION_STRING,
|
||||||
|
@ -1870,6 +1871,7 @@ struct OptionDesc {
|
||||||
{"developer", true, OPTION_IGNORE | OPTION_BOOL, "", false, "", nullptr },
|
{"developer", true, OPTION_IGNORE | OPTION_BOOL, "", false, "", nullptr },
|
||||||
{"jsbsim-output-directive-file", true, OPTION_STRING, "/sim/jsbsim/output-directive-file", false, "", nullptr },
|
{"jsbsim-output-directive-file", true, OPTION_STRING, "/sim/jsbsim/output-directive-file", false, "", nullptr },
|
||||||
{"disable-gui", false, OPTION_FUNC, "", false, "", fgOptDisableGUI },
|
{"disable-gui", false, OPTION_FUNC, "", false, "", fgOptDisableGUI },
|
||||||
|
{"composite-viewer", true, OPTION_INT, "/sim/rendering/composite-viewer-enabled", "", "", nullptr},
|
||||||
{nullptr, false, 0, nullptr, false, nullptr, nullptr}
|
{nullptr, false, 0, nullptr, false, nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -436,7 +436,7 @@ static InitPosResult setInitialPosFromCarrier( const string& carrier )
|
||||||
static InitPosResult checkCarrierSceneryLoaded(const SGSharedPtr<FGAICarrier> carrierRef)
|
static InitPosResult checkCarrierSceneryLoaded(const SGSharedPtr<FGAICarrier> carrierRef)
|
||||||
{
|
{
|
||||||
SGVec3d cartPos = carrierRef->getCartPos();
|
SGVec3d cartPos = carrierRef->getCartPos();
|
||||||
auto framestamp = globals->get_renderer()->getViewer()->getFrameStamp();
|
auto framestamp = globals->get_renderer()->getFrameStamp();
|
||||||
simgear::CheckSceneryVisitor csnv(globals->get_scenery()->getPager(),
|
simgear::CheckSceneryVisitor csnv(globals->get_scenery()->getPager(),
|
||||||
toOsg(cartPos),
|
toOsg(cartPos),
|
||||||
100.0 /* range in metres */,
|
100.0 /* range in metres */,
|
||||||
|
|
|
@ -213,7 +213,7 @@ public:
|
||||||
if ( NULL == osgDB::Registry::instance()->getReaderWriterForExtension(_type))
|
if ( NULL == osgDB::Registry::instance()->getReaderWriterForExtension(_type))
|
||||||
throw sg_format_exception("Unsupported image type: " + type, type);
|
throw sg_format_exception("Unsupported image type: " + type, type);
|
||||||
|
|
||||||
osg::Camera * camera = findLastCamera(globals->get_renderer()->getViewer(), window);
|
osg::Camera * camera = findLastCamera(globals->get_renderer()->getViewerBase(), window);
|
||||||
if ( NULL == camera)
|
if ( NULL == camera)
|
||||||
throw sg_error("Can't find a camera for window '" + window + "'");
|
throw sg_error("Can't find a camera for window '" + window + "'");
|
||||||
|
|
||||||
|
|
|
@ -371,7 +371,7 @@ bool FGStgTerrain::scenery_available(const SGGeod& position, double range_m)
|
||||||
|
|
||||||
SGVec3f p = SGVec3f::fromGeod(SGGeod::fromGeodM(position, elev));
|
SGVec3f p = SGVec3f::fromGeod(SGGeod::fromGeodM(position, elev));
|
||||||
osg::FrameStamp* framestamp
|
osg::FrameStamp* framestamp
|
||||||
= globals->get_renderer()->getViewer()->getFrameStamp();
|
= globals->get_renderer()->getFrameStamp();
|
||||||
|
|
||||||
FGScenery* pSceneryManager = globals->get_scenery();
|
FGScenery* pSceneryManager = globals->get_scenery();
|
||||||
simgear::CheckSceneryVisitor csnv(pSceneryManager->getPager(), toOsg(p), range_m, framestamp);
|
simgear::CheckSceneryVisitor csnv(pSceneryManager->getPager(), toOsg(p), range_m, framestamp);
|
||||||
|
|
|
@ -76,8 +76,8 @@ public:
|
||||||
|
|
||||||
if (_pagedLODMaximumProp->getType() == simgear::props::NONE) {
|
if (_pagedLODMaximumProp->getType() == simgear::props::NONE) {
|
||||||
// not set, use OSG default / environment value variable
|
// not set, use OSG default / environment value variable
|
||||||
osg::ref_ptr<osgViewer::Viewer> viewer(globals->get_renderer()->getViewer());
|
osg::ref_ptr<osgViewer::View> view(globals->get_renderer()->getView());
|
||||||
int current = viewer->getDatabasePager()->getTargetMaximumNumberOfPageLOD();
|
int current = view->getDatabasePager()->getTargetMaximumNumberOfPageLOD();
|
||||||
_pagedLODMaximumProp->setIntValue(current);
|
_pagedLODMaximumProp->setIntValue(current);
|
||||||
}
|
}
|
||||||
_pagedLODMaximumProp->addChangeListener(this, true);
|
_pagedLODMaximumProp->addChangeListener(this, true);
|
||||||
|
@ -106,9 +106,9 @@ public:
|
||||||
_manager->_enableCache = prop->getBoolValue();
|
_manager->_enableCache = prop->getBoolValue();
|
||||||
} else if (prop == _pagedLODMaximumProp) {
|
} else if (prop == _pagedLODMaximumProp) {
|
||||||
int v = prop->getIntValue();
|
int v = prop->getIntValue();
|
||||||
osg::ref_ptr<osgViewer::Viewer> viewer(globals->get_renderer()->getViewer());
|
osg::ref_ptr<osgViewer::View> view(globals->get_renderer()->getView());
|
||||||
if (viewer) {
|
if (view) {
|
||||||
osgDB::DatabasePager* pager = viewer->getDatabasePager();
|
osgDB::DatabasePager* pager = view->getDatabasePager();
|
||||||
if (pager) pager->setTargetMaximumNumberOfPageLOD(v);
|
if (pager) pager->setTargetMaximumNumberOfPageLOD(v);
|
||||||
}
|
}
|
||||||
} else if (prop == _lodDetailed || prop == _lodBareDelta || prop == _lodRoughDelta) {
|
} else if (prop == _lodDetailed || prop == _lodBareDelta || prop == _lodRoughDelta) {
|
||||||
|
@ -344,7 +344,7 @@ void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis)
|
||||||
|
|
||||||
// update timestamps, so all tiles scheduled now are *newer* than any tile previously loaded
|
// update timestamps, so all tiles scheduled now are *newer* than any tile previously loaded
|
||||||
osg::FrameStamp* framestamp
|
osg::FrameStamp* framestamp
|
||||||
= globals->get_renderer()->getViewer()->getFrameStamp();
|
= globals->get_renderer()->getFrameStamp();
|
||||||
tile_cache.set_current_time(framestamp->getReferenceTime());
|
tile_cache.set_current_time(framestamp->getReferenceTime());
|
||||||
|
|
||||||
SGBucket b;
|
SGBucket b;
|
||||||
|
@ -379,8 +379,7 @@ void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis)
|
||||||
*/
|
*/
|
||||||
void FGTileMgr::update_queues(bool& isDownloadingScenery)
|
void FGTileMgr::update_queues(bool& isDownloadingScenery)
|
||||||
{
|
{
|
||||||
osg::FrameStamp* framestamp
|
osg::FrameStamp* framestamp = globals->get_renderer()->getFrameStamp();
|
||||||
= globals->get_renderer()->getViewer()->getFrameStamp();
|
|
||||||
double current_time = framestamp->getReferenceTime();
|
double current_time = framestamp->getReferenceTime();
|
||||||
double vis = _visibilityMeters->getDoubleValue();
|
double vis = _visibilityMeters->getDoubleValue();
|
||||||
TileEntry *e;
|
TileEntry *e;
|
||||||
|
|
|
@ -12,6 +12,7 @@ set(SOURCES
|
||||||
splash.cxx
|
splash.cxx
|
||||||
view.cxx
|
view.cxx
|
||||||
viewmgr.cxx
|
viewmgr.cxx
|
||||||
|
sview.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
|
@ -24,6 +25,7 @@ set(HEADERS
|
||||||
splash.hxx
|
splash.hxx
|
||||||
view.hxx
|
view.hxx
|
||||||
viewmgr.hxx
|
viewmgr.hxx
|
||||||
|
sview.hxx
|
||||||
)
|
)
|
||||||
|
|
||||||
if (Qt5Core_FOUND)
|
if (Qt5Core_FOUND)
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "FGEventHandler.hxx"
|
#include "FGEventHandler.hxx"
|
||||||
#include "WindowBuilder.hxx"
|
#include "WindowBuilder.hxx"
|
||||||
#include "WindowSystemAdapter.hxx"
|
#include "WindowSystemAdapter.hxx"
|
||||||
|
#include "sview.hxx"
|
||||||
|
|
||||||
#include <simgear/math/SGRect.hxx>
|
#include <simgear/math/SGRect.hxx>
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
|
@ -192,8 +193,8 @@ typedef std::vector<SGPropertyNode_ptr> SGPropertyNodeVec;
|
||||||
|
|
||||||
osg::ref_ptr<CameraGroup> CameraGroup::_defaultGroup;
|
osg::ref_ptr<CameraGroup> CameraGroup::_defaultGroup;
|
||||||
|
|
||||||
CameraGroup::CameraGroup(osgViewer::Viewer* viewer) :
|
CameraGroup::CameraGroup(osgViewer::View* view) :
|
||||||
_viewer(viewer)
|
_viewer(view)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,6 +689,9 @@ void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
|
||||||
osg::ref_ptr<SGReaderWriterOptions> options =
|
osg::ref_ptr<SGReaderWriterOptions> options =
|
||||||
SGReaderWriterOptions::fromPath(globals->get_fg_root());
|
SGReaderWriterOptions::fromPath(globals->get_fg_root());
|
||||||
options->setPropertyNode(globals->get_props());
|
options->setPropertyNode(globals->get_props());
|
||||||
|
|
||||||
|
SViewSetCompositorParams(options, compositor_path);
|
||||||
|
|
||||||
Compositor *compositor = Compositor::create(_viewer,
|
Compositor *compositor = Compositor::create(_viewer,
|
||||||
window->gc,
|
window->gc,
|
||||||
viewport,
|
viewport,
|
||||||
|
@ -783,10 +787,10 @@ void CameraGroup::buildGUICamera(SGPropertyNode* cameraNode,
|
||||||
camera->setStats(0);
|
camera->setStats(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraGroup* CameraGroup::buildCameraGroup(osgViewer::Viewer* viewer,
|
CameraGroup* CameraGroup::buildCameraGroup(osgViewer::View* view,
|
||||||
SGPropertyNode* gnode)
|
SGPropertyNode* gnode)
|
||||||
{
|
{
|
||||||
CameraGroup* cgroup = new CameraGroup(viewer);
|
CameraGroup* cgroup = new CameraGroup(view);
|
||||||
cgroup->_listener.reset(new CameraGroupListener(cgroup, gnode));
|
cgroup->_listener.reset(new CameraGroupListener(cgroup, gnode));
|
||||||
|
|
||||||
for (int i = 0; i < gnode->nChildren(); ++i) {
|
for (int i = 0; i < gnode->nChildren(); ++i) {
|
||||||
|
@ -862,7 +866,7 @@ computeCameraIntersection(const CameraGroup *cgroup,
|
||||||
osgUtil::IntersectionVisitor iv(picker);
|
osgUtil::IntersectionVisitor iv(picker);
|
||||||
iv.setTraversalMask(simgear::PICK_BIT);
|
iv.setTraversalMask(simgear::PICK_BIT);
|
||||||
|
|
||||||
const_cast<CameraGroup *>(cgroup)->getViewer()->getCamera()->accept(iv);
|
const_cast<CameraGroup *>(cgroup)->getView()->getCamera()->accept(iv);
|
||||||
if (picker->containsIntersections()) {
|
if (picker->containsIntersections()) {
|
||||||
intersections = picker->getIntersections();
|
intersections = picker->getIntersections();
|
||||||
return true;
|
return true;
|
||||||
|
@ -921,7 +925,7 @@ void warpGUIPointer(CameraGroup* cgroup, int x, int y)
|
||||||
gw->getEventQueue()->mouseWarped(wx, wy);
|
gw->getEventQueue()->mouseWarped(wx, wy);
|
||||||
gw->requestWarpPointer(wx, wy);
|
gw->requestWarpPointer(wx, wy);
|
||||||
osgGA::GUIEventAdapter* eventState
|
osgGA::GUIEventAdapter* eventState
|
||||||
= cgroup->getViewer()->getEventQueue()->getCurrentEventState();
|
= cgroup->getView()->getEventQueue()->getCurrentEventState();
|
||||||
double viewerX
|
double viewerX
|
||||||
= (eventState->getXmin()
|
= (eventState->getXmin()
|
||||||
+ ((wx / double(traits->width))
|
+ ((wx / double(traits->width))
|
||||||
|
@ -930,10 +934,10 @@ void warpGUIPointer(CameraGroup* cgroup, int x, int y)
|
||||||
= (eventState->getYmin()
|
= (eventState->getYmin()
|
||||||
+ ((wyUp / double(traits->height))
|
+ ((wyUp / double(traits->height))
|
||||||
* (eventState->getYmax() - eventState->getYmin())));
|
* (eventState->getYmax() - eventState->getYmin())));
|
||||||
cgroup->getViewer()->getEventQueue()->mouseWarped(viewerX, viewerY);
|
cgroup->getView()->getEventQueue()->mouseWarped(viewerX, viewerY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraGroup::buildDefaultGroup(osgViewer::Viewer* viewer)
|
void CameraGroup::buildDefaultGroup(osgViewer::View* viewer)
|
||||||
{
|
{
|
||||||
// Look for windows, camera groups, and the old syntax of
|
// Look for windows, camera groups, and the old syntax of
|
||||||
// top-level cameras
|
// top-level cameras
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
#include <osg/TexGen>
|
#include <osg/TexGen>
|
||||||
#include <osgUtil/RenderBin>
|
#include <osgUtil/RenderBin>
|
||||||
|
#include <osgViewer/View>
|
||||||
|
|
||||||
#include <simgear/scene/viewer/Compositor.hxx>
|
#include <simgear/scene/viewer/Compositor.hxx>
|
||||||
|
|
||||||
|
@ -122,14 +123,14 @@ public:
|
||||||
/** Create a camera group associated with an osgViewer::Viewer.
|
/** Create a camera group associated with an osgViewer::Viewer.
|
||||||
* @param viewer the viewer
|
* @param viewer the viewer
|
||||||
*/
|
*/
|
||||||
CameraGroup(osgViewer::Viewer* viewer);
|
CameraGroup(osgViewer::View* viewer);
|
||||||
virtual ~CameraGroup();
|
virtual ~CameraGroup();
|
||||||
|
|
||||||
/** Set the default CameraGroup, which is the only one that
|
/** Set the default CameraGroup, which is the only one that
|
||||||
* matters at this time.
|
* matters at this time.
|
||||||
* @param group the group to set.
|
* @param group the group to set.
|
||||||
*/
|
*/
|
||||||
static void buildDefaultGroup(osgViewer::Viewer* viewer);
|
static void buildDefaultGroup(osgViewer::View* view);
|
||||||
static void setDefault(CameraGroup* group) { _defaultGroup = group; }
|
static void setDefault(CameraGroup* group) { _defaultGroup = group; }
|
||||||
/** Get the default CameraGroup.
|
/** Get the default CameraGroup.
|
||||||
* @return the default camera group.
|
* @return the default camera group.
|
||||||
|
@ -138,7 +139,7 @@ public:
|
||||||
/** Get the camera group's Viewer.
|
/** Get the camera group's Viewer.
|
||||||
* @return the viewer
|
* @return the viewer
|
||||||
*/
|
*/
|
||||||
osgViewer::Viewer* getViewer() { return _viewer.get(); }
|
osgViewer::View* getView() { return _viewer.get(); }
|
||||||
/** Create an osg::Camera from a property node and add it to the
|
/** Create an osg::Camera from a property node and add it to the
|
||||||
* camera group.
|
* camera group.
|
||||||
* @param cameraNode the property node.
|
* @param cameraNode the property node.
|
||||||
|
@ -192,7 +193,7 @@ protected:
|
||||||
|
|
||||||
typedef std::vector<osg::ref_ptr<CameraInfo>> CameraList;
|
typedef std::vector<osg::ref_ptr<CameraInfo>> CameraList;
|
||||||
CameraList _cameras;
|
CameraList _cameras;
|
||||||
osg::ref_ptr<osgViewer::Viewer> _viewer;
|
osg::ref_ptr<osgViewer::View> _viewer;
|
||||||
static osg::ref_ptr<CameraGroup> _defaultGroup;
|
static osg::ref_ptr<CameraGroup> _defaultGroup;
|
||||||
std::unique_ptr<CameraGroupListener> _listener;
|
std::unique_ptr<CameraGroupListener> _listener;
|
||||||
|
|
||||||
|
@ -206,7 +207,7 @@ protected:
|
||||||
* @param wbuilder the window builder to be used for this camera group.
|
* @param wbuilder the window builder to be used for this camera group.
|
||||||
* @param the camera group property node.
|
* @param the camera group property node.
|
||||||
*/
|
*/
|
||||||
static CameraGroup* buildCameraGroup(osgViewer::Viewer* viewer,
|
static CameraGroup* buildCameraGroup(osgViewer::View* viewer,
|
||||||
SGPropertyNode* node);
|
SGPropertyNode* node);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
#include "CameraGroup.hxx"
|
#include "CameraGroup.hxx"
|
||||||
#include "FGEventHandler.hxx"
|
#include "FGEventHandler.hxx"
|
||||||
#include "WindowSystemAdapter.hxx"
|
#include "WindowSystemAdapter.hxx"
|
||||||
|
#include "WindowBuilder.hxx"
|
||||||
#include "renderer.hxx"
|
#include "renderer.hxx"
|
||||||
|
#include "sview.hxx"
|
||||||
|
|
||||||
#ifdef SG_MAC
|
#ifdef SG_MAC
|
||||||
// hack - during interactive resize on Mac, OSG queues and then flushes
|
// hack - during interactive resize on Mac, OSG queues and then flushes
|
||||||
|
@ -85,12 +87,18 @@ bool
|
||||||
eventToViewport(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us,
|
eventToViewport(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us,
|
||||||
int& x, int& y)
|
int& x, int& y)
|
||||||
{
|
{
|
||||||
|
flightgear::WindowBuilder* window_builder = flightgear::WindowBuilder::getWindowBuilder();
|
||||||
|
flightgear::GraphicsWindow* main_window = window_builder->getDefaultWindow();
|
||||||
|
|
||||||
x = -1;
|
x = -1;
|
||||||
y = -1;
|
y = -1;
|
||||||
|
|
||||||
const osg::GraphicsContext* eventGC = ea.getGraphicsContext();
|
const osg::GraphicsContext* eventGC = ea.getGraphicsContext();
|
||||||
if( !eventGC )
|
if( !eventGC )
|
||||||
return false; // TODO how can this happen?
|
return false; // TODO how can this happen?
|
||||||
|
if (eventGC != main_window->gc.get()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const osg::GraphicsContext::Traits* traits = eventGC->getTraits();
|
const osg::GraphicsContext::Traits* traits = eventGC->getTraits();
|
||||||
osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault());
|
osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault());
|
||||||
if (!guiCamera)
|
if (!guiCamera)
|
||||||
|
@ -115,6 +123,20 @@ eventToViewport(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A hack for when we are linked with OSG-3.4 and CompositeViewer is
|
||||||
|
enabled. It seems that OSG-3.4 incorrectly calls our event handler for
|
||||||
|
extra view windows (e.g. resize/close events), so we try to detect
|
||||||
|
this. Unfortunately OSG also messes up <ea>'s graphics context pointer so this
|
||||||
|
does't alwys work. */
|
||||||
|
bool isMainWindow(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
bool ret = eventToViewport(ea, us, x, y);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FGEventHandler::handle(const osgGA::GUIEventAdapter& ea,
|
bool FGEventHandler::handle(const osgGA::GUIEventAdapter& ea,
|
||||||
|
@ -224,6 +246,9 @@ bool FGEventHandler::handle(const osgGA::GUIEventAdapter& ea,
|
||||||
return true;
|
return true;
|
||||||
case osgGA::GUIEventAdapter::RESIZE:
|
case osgGA::GUIEventAdapter::RESIZE:
|
||||||
SG_LOG(SG_VIEW, SG_DEBUG, "FGEventHandler::handle: RESIZE event " << ea.getWindowHeight() << " x " << ea.getWindowWidth() << ", resizable: " << resizable);
|
SG_LOG(SG_VIEW, SG_DEBUG, "FGEventHandler::handle: RESIZE event " << ea.getWindowHeight() << " x " << ea.getWindowWidth() << ", resizable: " << resizable);
|
||||||
|
if (!isMainWindow(ea, us)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
CameraGroup::getDefault()->resized();
|
CameraGroup::getDefault()->resized();
|
||||||
if (resizable)
|
if (resizable)
|
||||||
globals->get_renderer()->resize(ea.getWindowWidth(), ea.getWindowHeight());
|
globals->get_renderer()->resize(ea.getWindowWidth(), ea.getWindowHeight());
|
||||||
|
@ -236,6 +261,10 @@ bool FGEventHandler::handle(const osgGA::GUIEventAdapter& ea,
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
case osgGA::GUIEventAdapter::CLOSE_WINDOW:
|
case osgGA::GUIEventAdapter::CLOSE_WINDOW:
|
||||||
|
if (!isMainWindow(ea, us)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Fall through.
|
||||||
case osgGA::GUIEventAdapter::QUIT_APPLICATION:
|
case osgGA::GUIEventAdapter::QUIT_APPLICATION:
|
||||||
fgOSExit(0);
|
fgOSExit(0);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -275,13 +275,13 @@ PUICamera::~PUICamera()
|
||||||
// depending on if we're doing shutdown or reset, various things can be
|
// depending on if we're doing shutdown or reset, various things can be
|
||||||
// null here.
|
// null here.
|
||||||
auto renderer = globals->get_renderer();
|
auto renderer = globals->get_renderer();
|
||||||
auto viewer = renderer ? renderer->getViewer() : nullptr;
|
auto view = renderer ? renderer->getView() : nullptr;
|
||||||
if (viewer) {
|
if (view) {
|
||||||
viewer->removeEventHandler(_eventHandler);
|
view->removeEventHandler(_eventHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PUICamera::init(osg::Group* parent, osgViewer::Viewer* viewer)
|
void PUICamera::init(osg::Group* parent, osgViewer::View* view)
|
||||||
{
|
{
|
||||||
setName("PUI FBO camera");
|
setName("PUI FBO camera");
|
||||||
|
|
||||||
|
@ -351,7 +351,7 @@ void PUICamera::init(osg::Group* parent, osgViewer::Viewer* viewer)
|
||||||
// the rendering order (i.e top-most UI layer has the front-most event
|
// the rendering order (i.e top-most UI layer has the front-most event
|
||||||
// handler)
|
// handler)
|
||||||
_eventHandler = new PUIEventHandler(this);
|
_eventHandler = new PUIEventHandler(this);
|
||||||
viewer->getEventHandlers().push_front(_eventHandler);
|
view->getEventHandlers().push_front(_eventHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove once we require OSG 3.4
|
// remove once we require OSG 3.4
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <osg/Camera>
|
#include <osg/Camera>
|
||||||
#include <osg/Version>
|
#include <osg/Version>
|
||||||
|
#include <osgViewer/View>
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
|
@ -51,7 +52,7 @@ public:
|
||||||
// osg::Camera already defines a resize() so use this name
|
// osg::Camera already defines a resize() so use this name
|
||||||
void resizeUi(int width, int height);
|
void resizeUi(int width, int height);
|
||||||
|
|
||||||
void init(osg::Group* parent, osgViewer::Viewer* viewer);
|
void init(osg::Group* parent, osgViewer::View* view);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void manuallyResizeFBO(int width, int height);
|
void manuallyResizeFBO(int width, int height);
|
||||||
|
|
|
@ -189,7 +189,7 @@ class NotifyLevelListener : public SGPropertyChangeListener
|
||||||
public:
|
public:
|
||||||
void valueChanged(SGPropertyNode* node)
|
void valueChanged(SGPropertyNode* node)
|
||||||
{
|
{
|
||||||
osg::NotifySeverity severity = osg::WARN;
|
osg::NotifySeverity severity = osg::getNotifyLevel();
|
||||||
string val = simgear::strutils::lowercase(node->getStringValue());
|
string val = simgear::strutils::lowercase(node->getStringValue());
|
||||||
|
|
||||||
if (val == "fatal") {
|
if (val == "fatal") {
|
||||||
|
@ -216,6 +216,61 @@ void fgOSOpenWindow(bool stencil)
|
||||||
{
|
{
|
||||||
osg::setNotifyHandler(new NotifyLogger);
|
osg::setNotifyHandler(new NotifyLogger);
|
||||||
|
|
||||||
|
auto composite_viewer = dynamic_cast<osgViewer::CompositeViewer*>(
|
||||||
|
globals->get_renderer()->getViewerBase()
|
||||||
|
);
|
||||||
|
if (0) {}
|
||||||
|
else if (composite_viewer) {
|
||||||
|
/* We are using CompositeViewer. */
|
||||||
|
SG_LOG(SG_VIEW, SG_ALERT, "Using CompositeViewer");
|
||||||
|
osgViewer::ViewerBase* viewer = globals->get_renderer()->getViewerBase();
|
||||||
|
SG_LOG(SG_VIEW, SG_ALERT, "Creating osgViewer::View");
|
||||||
|
osgViewer::View* view = new osgViewer::View;
|
||||||
|
view->setFrameStamp(composite_viewer->getFrameStamp());
|
||||||
|
globals->get_renderer()->setView(view);
|
||||||
|
assert(globals->get_renderer()->getView() == view);
|
||||||
|
view->setDatabasePager(FGScenery::getPagerSingleton());
|
||||||
|
|
||||||
|
// https://www.mail-archive.com/osg-users@lists.openscenegraph.org/msg29820.html
|
||||||
|
view->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, false);
|
||||||
|
osg::GraphicsContext::createNewContextID();
|
||||||
|
|
||||||
|
//viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
|
||||||
|
|
||||||
|
std::string mode;
|
||||||
|
mode = fgGetString("/sim/rendering/multithreading-mode", "SingleThreaded");
|
||||||
|
SG_LOG( SG_VIEW, SG_INFO, "mode=" << mode);
|
||||||
|
if (mode == "AutomaticSelection")
|
||||||
|
viewer->setThreadingModel(osgViewer::Viewer::AutomaticSelection);
|
||||||
|
else if (mode == "CullDrawThreadPerContext")
|
||||||
|
viewer->setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext);
|
||||||
|
else if (mode == "DrawThreadPerContext")
|
||||||
|
viewer->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
|
||||||
|
else if (mode == "CullThreadPerCameraDrawThreadPerContext")
|
||||||
|
viewer->setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext);
|
||||||
|
else
|
||||||
|
viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
|
||||||
|
|
||||||
|
WindowBuilder::initWindowBuilder(stencil);
|
||||||
|
CameraGroup::buildDefaultGroup(view);
|
||||||
|
|
||||||
|
FGEventHandler* manipulator = globals->get_renderer()->getEventHandler();
|
||||||
|
WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
|
||||||
|
if (wsa->windows.size() != 1) {
|
||||||
|
manipulator->setResizable(false);
|
||||||
|
}
|
||||||
|
view->getCamera()->setProjectionResizePolicy(osg::Camera::FIXED);
|
||||||
|
view->addEventHandler(manipulator);
|
||||||
|
// Let FG handle the escape key with a confirmation
|
||||||
|
viewer->setKeyEventSetsDone(0);
|
||||||
|
// The viewer won't start without some root.
|
||||||
|
view->setSceneData(new osg::Group);
|
||||||
|
globals->get_renderer()->setView(view);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Not using CompositeViewer. */
|
||||||
|
SG_LOG(SG_VIEW, SG_DEBUG, "Not CompositeViewer.");
|
||||||
|
SG_LOG(SG_VIEW, SG_DEBUG, "Creating osgViewer::Viewer");
|
||||||
viewer = new osgViewer::Viewer;
|
viewer = new osgViewer::Viewer;
|
||||||
viewer->setDatabasePager(FGScenery::getPagerSingleton());
|
viewer->setDatabasePager(FGScenery::getPagerSingleton());
|
||||||
|
|
||||||
|
@ -247,7 +302,8 @@ void fgOSOpenWindow(bool stencil)
|
||||||
viewer->setKeyEventSetsDone(0);
|
viewer->setKeyEventSetsDone(0);
|
||||||
// The viewer won't start without some root.
|
// The viewer won't start without some root.
|
||||||
viewer->setSceneData(new osg::Group);
|
viewer->setSceneData(new osg::Group);
|
||||||
globals->get_renderer()->setViewer(viewer.get());
|
globals->get_renderer()->setView(viewer.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SGPropertyNode* simHost = 0, *simFrameCount, *simTotalHostTime, *simFrameResetCount, *frameWait;
|
SGPropertyNode* simHost = 0, *simFrameCount, *simTotalHostTime, *simFrameResetCount, *frameWait;
|
||||||
void fgOSResetProperties()
|
void fgOSResetProperties()
|
||||||
|
@ -286,8 +342,9 @@ static int status = 0;
|
||||||
|
|
||||||
void fgOSExit(int code)
|
void fgOSExit(int code)
|
||||||
{
|
{
|
||||||
viewer->setDone(true);
|
FGRenderer* renderer = globals->get_renderer();
|
||||||
viewer->getDatabasePager()->cancel();
|
renderer->getViewerBase()->setDone(true);
|
||||||
|
renderer->getView()->getDatabasePager()->cancel();
|
||||||
status = code;
|
status = code;
|
||||||
|
|
||||||
// otherwise we crash if OSG does logging during static destruction, eg
|
// otherwise we crash if OSG does logging during static destruction, eg
|
||||||
|
@ -299,12 +356,13 @@ SGTimeStamp _lastUpdate;
|
||||||
|
|
||||||
int fgOSMainLoop()
|
int fgOSMainLoop()
|
||||||
{
|
{
|
||||||
viewer->setReleaseContextAtEndOfFrameHint(false);
|
osgViewer::ViewerBase* viewer_base = globals->get_renderer()->getViewerBase();
|
||||||
if (!viewer->isRealized()) {
|
viewer_base->setReleaseContextAtEndOfFrameHint(false);
|
||||||
viewer->realize();
|
if (!viewer_base->isRealized()) {
|
||||||
|
viewer_base->realize();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!viewer->done()) {
|
while (!viewer_base->done()) {
|
||||||
fgIdleHandler idleFunc = globals->get_renderer()->getEventHandler()->getIdleHandler();
|
fgIdleHandler idleFunc = globals->get_renderer()->getEventHandler()->getIdleHandler();
|
||||||
if (idleFunc)
|
if (idleFunc)
|
||||||
{
|
{
|
||||||
|
@ -338,7 +396,7 @@ int fgOSMainLoop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
globals->get_renderer()->update();
|
globals->get_renderer()->update();
|
||||||
viewer->frame( globals->get_sim_time_sec() );
|
viewer_base->frame( globals->get_sim_time_sec() );
|
||||||
}
|
}
|
||||||
|
|
||||||
flightgear::addSentryBreadcrumb("main loop exited", "info");
|
flightgear::addSentryBreadcrumb("main loop exited", "info");
|
||||||
|
@ -383,13 +441,16 @@ void fgOSInit(int* argc, char** argv)
|
||||||
|
|
||||||
void fgOSCloseWindow()
|
void fgOSCloseWindow()
|
||||||
{
|
{
|
||||||
if (viewer) {
|
if (globals && globals->get_renderer()) {
|
||||||
|
osgViewer::ViewerBase* viewer_base = globals->get_renderer()->getViewerBase();
|
||||||
|
if (viewer_base) {
|
||||||
// https://code.google.com/p/flightgear-bugs/issues/detail?id=1291
|
// https://code.google.com/p/flightgear-bugs/issues/detail?id=1291
|
||||||
// https://sourceforge.net/p/flightgear/codetickets/1830/
|
// https://sourceforge.net/p/flightgear/codetickets/1830/
|
||||||
// explicitly stop threading before we delete the renderer or
|
// explicitly stop threading before we delete the renderer or
|
||||||
// viewMgr (which ultimately holds refs to the CameraGroup, and
|
// viewMgr (which ultimately holds refs to the CameraGroup, and
|
||||||
// GraphicsContext)
|
// GraphicsContext)
|
||||||
viewer->stopThreading();
|
viewer_base->stopThreading();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FGScenery::resetPagerSingleton();
|
FGScenery::resetPagerSingleton();
|
||||||
flightgear::CameraGroup::setDefault(NULL);
|
flightgear::CameraGroup::setDefault(NULL);
|
||||||
|
@ -399,8 +460,9 @@ void fgOSCloseWindow()
|
||||||
|
|
||||||
void fgOSFullScreen()
|
void fgOSFullScreen()
|
||||||
{
|
{
|
||||||
|
osgViewer::ViewerBase* viewer_base = globals->get_renderer()->getViewerBase();
|
||||||
std::vector<osgViewer::GraphicsWindow*> windows;
|
std::vector<osgViewer::GraphicsWindow*> windows;
|
||||||
viewer->getWindows(windows);
|
viewer_base->getWindows(windows);
|
||||||
|
|
||||||
if (windows.empty())
|
if (windows.empty())
|
||||||
return; // Huh?!?
|
return; // Huh?!?
|
||||||
|
@ -544,11 +606,14 @@ static int _cursor = -1;
|
||||||
void fgSetMouseCursor(int cursor)
|
void fgSetMouseCursor(int cursor)
|
||||||
{
|
{
|
||||||
_cursor = cursor;
|
_cursor = cursor;
|
||||||
if (!viewer)
|
if (!globals || !globals->get_renderer())
|
||||||
|
return;
|
||||||
|
osgViewer::ViewerBase* viewer_base = globals->get_renderer()->getViewerBase();
|
||||||
|
if (!viewer_base)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<osgViewer::GraphicsWindow*> windows;
|
std::vector<osgViewer::GraphicsWindow*> windows;
|
||||||
viewer->getWindows(windows);
|
viewer_base->getWindows(windows);
|
||||||
for (osgViewer::GraphicsWindow* gw : windows) {
|
for (osgViewer::GraphicsWindow* gw : windows) {
|
||||||
setMouseCursor(gw, cursor);
|
setMouseCursor(gw, cursor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ fgviewerMain(int argc, char** argv)
|
||||||
// construct the viewer.
|
// construct the viewer.
|
||||||
FGRenderer* fgrenderer = new FGRenderer();
|
FGRenderer* fgrenderer = new FGRenderer();
|
||||||
osgViewer::Viewer* viewer = new osgViewer::Viewer(arguments);
|
osgViewer::Viewer* viewer = new osgViewer::Viewer(arguments);
|
||||||
fgrenderer->setViewer(viewer);
|
fgrenderer->setView(viewer);
|
||||||
osg::Camera* camera = viewer->getCamera();
|
osg::Camera* camera = viewer->getCamera();
|
||||||
osgViewer::Renderer* renderer
|
osgViewer::Renderer* renderer
|
||||||
= static_cast<osgViewer::Renderer*>(camera->getRenderer());
|
= static_cast<osgViewer::Renderer*>(camera->getRenderer());
|
||||||
|
|
|
@ -359,8 +359,8 @@ FGRenderer::~FGRenderer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace the viewer's scene completely
|
// replace the viewer's scene completely
|
||||||
if (getViewer()) {
|
if (getView()) {
|
||||||
getViewer()->setSceneData(new osg::Group);
|
getView()->setSceneData(new osg::Group);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete _sky;
|
delete _sky;
|
||||||
|
@ -398,28 +398,39 @@ FGRenderer::addChangeListener(SGPropertyChangeListener* l, const char* path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize various GL/view parameters
|
// Initialize various GL/view parameters
|
||||||
|
//
|
||||||
|
// Note that this appears to be called *after* FGRenderer::init().
|
||||||
|
//
|
||||||
void
|
void
|
||||||
FGRenderer::preinit( void )
|
FGRenderer::preinit( void )
|
||||||
{
|
{
|
||||||
// important that we reset the viewer sceneData here, to ensure the reference
|
// important that we reset the viewer sceneData here, to ensure the reference
|
||||||
// time for everything is in sync; otherwise on reset the Viewer and
|
// time for everything is in sync; otherwise on reset the Viewer and
|
||||||
// GraphicsWindow clocks are out of sync.
|
// GraphicsWindow clocks are out of sync.
|
||||||
osgViewer::Viewer* viewer = getViewer();
|
osgViewer::View* view = getView();
|
||||||
viewer->setName("osgViewer");
|
view->setName("osgViewer");
|
||||||
_viewerSceneRoot = new osg::Group;
|
_viewerSceneRoot = new osg::Group;
|
||||||
_viewerSceneRoot->setName("viewerSceneRoot");
|
_viewerSceneRoot->setName("viewerSceneRoot");
|
||||||
viewer->setSceneData(_viewerSceneRoot);
|
view->setSceneData(_viewerSceneRoot);
|
||||||
|
view->setDatabasePager(FGScenery::getPagerSingleton());
|
||||||
|
|
||||||
_quickDrawable = nullptr;
|
_quickDrawable = nullptr;
|
||||||
_splash = new SplashScreen;
|
_splash = new SplashScreen;
|
||||||
_viewerSceneRoot->addChild(_splash);
|
_viewerSceneRoot->addChild(_splash);
|
||||||
|
|
||||||
|
if (composite_viewer) {
|
||||||
|
// Nothing to do - composite_viewer->addView() will tell view to use
|
||||||
|
// composite_viewer's FrameStamp.
|
||||||
|
}
|
||||||
|
else {
|
||||||
_frameStamp = new osg::FrameStamp;
|
_frameStamp = new osg::FrameStamp;
|
||||||
viewer->setFrameStamp(_frameStamp.get());
|
view->setFrameStamp(_frameStamp.get());
|
||||||
|
}
|
||||||
|
|
||||||
// Scene doesn't seem to pass the frame stamp to the update
|
// Scene doesn't seem to pass the frame stamp to the update
|
||||||
// visitor automatically.
|
// visitor automatically.
|
||||||
_updateVisitor->setFrameStamp(_frameStamp.get());
|
_updateVisitor->setFrameStamp(getFrameStamp());
|
||||||
viewer->setUpdateVisitor(_updateVisitor.get());
|
getViewerBase()->setUpdateVisitor(_updateVisitor.get());
|
||||||
fgSetDouble("/sim/startup/splash-alpha", 1.0);
|
fgSetDouble("/sim/startup/splash-alpha", 1.0);
|
||||||
|
|
||||||
// hide the menubar if it overlaps the window, so the splash screen
|
// hide the menubar if it overlaps the window, so the splash screen
|
||||||
|
@ -436,6 +447,31 @@ FGRenderer::init( void )
|
||||||
|
|
||||||
sgUserDataInit( globals->get_props() );
|
sgUserDataInit( globals->get_props() );
|
||||||
|
|
||||||
|
SGPropertyNode* composite_viewer_enabled_prop = fgGetNode("/sim/rendering/composite-viewer-enabled", true);
|
||||||
|
// After we've read composite_viewer_enabled_prop here, changing its value
|
||||||
|
// will have no affect, so mark it as read-only for clarity.
|
||||||
|
composite_viewer_enabled_prop->setAttributes(SGPropertyNode::READ);
|
||||||
|
if (composite_viewer_enabled_prop->getBoolValue()) {
|
||||||
|
const char* osg_version = osgGetVersion();
|
||||||
|
if (simgear::strutils::starts_with(osg_version, "3.4")) {
|
||||||
|
SG_LOG( SG_GENERAL, SG_POPUP,
|
||||||
|
"CompositeViewer is enabled and requires OpenSceneGraph-3.6, but\n"
|
||||||
|
" Flightgear has been built with OpenSceneGraph-" << osg_version << ".\n"
|
||||||
|
" There may be problems when opening/closing extra view windows.\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
composite_viewer_enabled = 1;
|
||||||
|
SG_LOG(SG_VIEW, SG_ALERT, "Creating osgViewer::CompositeViewer");
|
||||||
|
composite_viewer = new osgViewer::CompositeViewer;
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/15207076/openscenegraph-and-multiple-viewers
|
||||||
|
composite_viewer->setReleaseContextAtEndOfFrameHint(false);
|
||||||
|
composite_viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
composite_viewer_enabled = 0;
|
||||||
|
SG_LOG(SG_VIEW, SG_ALERT, "Not creating osgViewer::CompositeViewer");
|
||||||
|
}
|
||||||
_scenery_loaded = fgGetNode("/sim/sceneryloaded", true);
|
_scenery_loaded = fgGetNode("/sim/sceneryloaded", true);
|
||||||
_position_finalized = fgGetNode("/sim/position-finalized", true);
|
_position_finalized = fgGetNode("/sim/position-finalized", true);
|
||||||
|
|
||||||
|
@ -542,7 +578,7 @@ void FGRenderer::setupRoot()
|
||||||
void
|
void
|
||||||
FGRenderer::setupView( void )
|
FGRenderer::setupView( void )
|
||||||
{
|
{
|
||||||
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
|
osgViewer::View* view = globals->get_renderer()->getView();
|
||||||
osg::initNotifyLevel();
|
osg::initNotifyLevel();
|
||||||
|
|
||||||
// The number of polygon-offset "units" to place between layers. In
|
// The number of polygon-offset "units" to place between layers. In
|
||||||
|
@ -571,7 +607,7 @@ FGRenderer::setupView( void )
|
||||||
fgGetNode("/environment", true),
|
fgGetNode("/environment", true),
|
||||||
opt.get());
|
opt.get());
|
||||||
|
|
||||||
viewer->getCamera()
|
view->getCamera()
|
||||||
->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
||||||
|
|
||||||
|
|
||||||
|
@ -647,10 +683,12 @@ FGRenderer::setupView( void )
|
||||||
|
|
||||||
#if defined(HAVE_PUI)
|
#if defined(HAVE_PUI)
|
||||||
_puiCamera = new flightgear::PUICamera;
|
_puiCamera = new flightgear::PUICamera;
|
||||||
_puiCamera->init(guiCamera, viewer);
|
_puiCamera->init(guiCamera, view);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_QQ_UI)
|
#if defined(ENABLE_QQ_UI)
|
||||||
|
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(view);
|
||||||
|
if (viewer) {
|
||||||
std::string rootQMLPath = fgGetString("/sim/gui/qml-root-path");
|
std::string rootQMLPath = fgGetString("/sim/gui/qml-root-path");
|
||||||
auto graphicsWindow = dynamic_cast<osgViewer::GraphicsWindow*>(guiCamera->getGraphicsContext());
|
auto graphicsWindow = dynamic_cast<osgViewer::GraphicsWindow*>(guiCamera->getGraphicsContext());
|
||||||
|
|
||||||
|
@ -664,6 +702,7 @@ FGRenderer::setupView( void )
|
||||||
qqGeode->addDrawable(_quickDrawable);
|
qqGeode->addDrawable(_quickDrawable);
|
||||||
guiCamera->addChild(qqGeode);
|
guiCamera->addChild(qqGeode);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
guiCamera->insertChild(0, FGPanelNode::create2DPanelNode());
|
guiCamera->insertChild(0, FGPanelNode::create2DPanelNode());
|
||||||
}
|
}
|
||||||
|
@ -706,7 +745,6 @@ FGRenderer::update( ) {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
|
|
||||||
|
|
||||||
if (_splash_alpha->getDoubleValue()>0.0)
|
if (_splash_alpha->getDoubleValue()>0.0)
|
||||||
{
|
{
|
||||||
|
@ -748,8 +786,21 @@ FGRenderer::update( ) {
|
||||||
// Force update of center dependent values ...
|
// Force update of center dependent values ...
|
||||||
current__view->set_dirty();
|
current__view->set_dirty();
|
||||||
|
|
||||||
osg::Camera *camera = viewer->getCamera();
|
assert(composite_viewer_enabled != -1);
|
||||||
|
std::vector<osg::Camera*> cameras;
|
||||||
|
if (composite_viewer) {
|
||||||
|
assert(!viewer);
|
||||||
|
unsigned n = composite_viewer->getNumViews();
|
||||||
|
for (unsigned i=0; i<n; ++i) {
|
||||||
|
osgViewer::View* view = composite_viewer->getView(i);
|
||||||
|
osg::Camera* camera = view->getCamera();
|
||||||
|
cameras.push_back(camera);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cameras.push_back(viewer->getCamera());
|
||||||
|
}
|
||||||
|
for (osg::Camera* camera: cameras) {
|
||||||
osg::Vec4 clear_color = _altitude_ft->getDoubleValue() < 250000
|
osg::Vec4 clear_color = _altitude_ft->getDoubleValue() < 250000
|
||||||
? toOsg(l->adj_fog_color())
|
? toOsg(l->adj_fog_color())
|
||||||
// skydome ends at ~262000ft (default rendering)
|
// skydome ends at ~262000ft (default rendering)
|
||||||
|
@ -762,9 +813,10 @@ FGRenderer::update( ) {
|
||||||
updateSky();
|
updateSky();
|
||||||
|
|
||||||
// need to call the update visitor once
|
// need to call the update visitor once
|
||||||
_frameStamp->setCalendarTime(*globals->get_time_params()->getGmt());
|
getFrameStamp()->setCalendarTime(*globals->get_time_params()->getGmt());
|
||||||
_updateVisitor->setViewData(current__view->getViewPosition(),
|
_updateVisitor->setViewData(current__view->getViewPosition(),
|
||||||
current__view->getViewOrientation());
|
current__view->getViewOrientation());
|
||||||
|
//_updateVisitor->setViewData(eye2, center3);
|
||||||
SGVec3f direction(l->sun_vec()[0], l->sun_vec()[1], l->sun_vec()[2]);
|
SGVec3f direction(l->sun_vec()[0], l->sun_vec()[1], l->sun_vec()[2]);
|
||||||
_updateVisitor->setLight(direction, l->scene_ambient(),
|
_updateVisitor->setLight(direction, l->scene_ambient(),
|
||||||
l->scene_diffuse(), l->scene_specular(),
|
l->scene_diffuse(), l->scene_specular(),
|
||||||
|
@ -781,6 +833,7 @@ FGRenderer::update( ) {
|
||||||
camera->setCullMaskLeft(cullMask);
|
camera->setCullMaskLeft(cullMask);
|
||||||
camera->setCullMaskRight(cullMask);
|
camera->setCullMaskRight(cullMask);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FGRenderer::updateSky()
|
FGRenderer::updateSky()
|
||||||
|
@ -958,11 +1011,66 @@ PickList FGRenderer::pick(const osg::Vec2& windowPos)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
osgViewer::ViewerBase* FGRenderer::getViewerBase()
|
||||||
FGRenderer::setViewer(osgViewer::Viewer* viewer_)
|
|
||||||
{
|
{
|
||||||
|
if (composite_viewer) {
|
||||||
|
return composite_viewer.get();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return viewer.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
osgViewer::View* FGRenderer::getView()
|
||||||
|
{
|
||||||
|
assert(composite_viewer_enabled != -1);
|
||||||
|
if (composite_viewer) {
|
||||||
|
assert(composite_viewer->getNumViews());
|
||||||
|
return composite_viewer->getView(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return viewer.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const osgViewer::View* FGRenderer::getView() const
|
||||||
|
{
|
||||||
|
FGRenderer* this_ = const_cast<FGRenderer*>(this);
|
||||||
|
return this_->getView();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGRenderer::setView(osgViewer::View* view)
|
||||||
|
{
|
||||||
|
assert(composite_viewer_enabled != -1);
|
||||||
|
if (composite_viewer) {
|
||||||
|
if (composite_viewer->getNumViews() == 0) {
|
||||||
|
SG_LOG(SG_VIEW, SG_ALERT, "adding view to composite_viewer.");
|
||||||
|
composite_viewer->stopThreading();
|
||||||
|
composite_viewer->addView(view);
|
||||||
|
composite_viewer->startThreading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
osgViewer::Viewer* viewer_ = dynamic_cast<osgViewer::Viewer*>(view);
|
||||||
|
assert(viewer_);
|
||||||
viewer = viewer_;
|
viewer = viewer_;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::FrameStamp*
|
||||||
|
FGRenderer::getFrameStamp()
|
||||||
|
{
|
||||||
|
assert(composite_viewer_enabled != -1);
|
||||||
|
if (composite_viewer) {
|
||||||
|
assert(!viewer);
|
||||||
|
return composite_viewer->getFrameStamp();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(viewer);
|
||||||
|
return viewer->getFrameStamp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FGRenderer::setEventHandler(FGEventHandler* eventHandler_)
|
FGRenderer::setEventHandler(FGEventHandler* eventHandler_)
|
||||||
|
@ -991,8 +1099,8 @@ FGRenderer::setPlanes( double zNear, double zFar )
|
||||||
bool
|
bool
|
||||||
fgDumpSceneGraphToFile(const char* filename)
|
fgDumpSceneGraphToFile(const char* filename)
|
||||||
{
|
{
|
||||||
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
|
osgViewer::View* view = globals->get_renderer()->getView();
|
||||||
return osgDB::writeNodeFile(*viewer->getSceneData(), filename);
|
return osgDB::writeNodeFile(*view->getSceneData(), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -1199,14 +1307,14 @@ protected:
|
||||||
|
|
||||||
bool printVisibleSceneInfo(FGRenderer* renderer)
|
bool printVisibleSceneInfo(FGRenderer* renderer)
|
||||||
{
|
{
|
||||||
osgViewer::Viewer* viewer = renderer->getViewer();
|
osgViewer::View* view = renderer->getView();
|
||||||
VisibleSceneInfoVistor vsv;
|
VisibleSceneInfoVistor vsv;
|
||||||
Viewport* vp = 0;
|
Viewport* vp = 0;
|
||||||
if (!viewer->getCamera()->getViewport() && viewer->getNumSlaves() > 0) {
|
if (!view->getCamera()->getViewport() && view->getNumSlaves() > 0) {
|
||||||
const osg::View::Slave& slave = viewer->getSlave(0);
|
const osg::View::Slave& slave = view->getSlave(0);
|
||||||
vp = slave._camera->getViewport();
|
vp = slave._camera->getViewport();
|
||||||
}
|
}
|
||||||
vsv.doTraversal(viewer->getCamera(), viewer->getSceneData(), vp);
|
vsv.doTraversal(view->getCamera(), view->getSceneData(), vp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
#include <osg/Vec2>
|
#include <osg/Vec2>
|
||||||
#include <osg/Vec3>
|
#include <osg/Vec3>
|
||||||
|
|
||||||
|
#include <osgViewer/CompositeViewer>
|
||||||
|
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
class Camera;
|
class Camera;
|
||||||
|
@ -62,11 +65,19 @@ public:
|
||||||
*/
|
*/
|
||||||
PickList pick(const osg::Vec2& windowPos);
|
PickList pick(const osg::Vec2& windowPos);
|
||||||
|
|
||||||
|
/* Returns either composite_viewer or viewer. */
|
||||||
|
osgViewer::ViewerBase* getViewerBase();
|
||||||
|
|
||||||
/** Get and set the OSG Viewer object, if any.
|
/** Get and set the OSG Viewer object, if any.
|
||||||
*/
|
*/
|
||||||
osgViewer::Viewer* getViewer() { return viewer.get(); }
|
osgViewer::View* getView();
|
||||||
const osgViewer::Viewer* getViewer() const { return viewer.get(); }
|
const osgViewer::View* getView() const;
|
||||||
void setViewer(osgViewer::Viewer* viewer);
|
void setView(osgViewer::View* view);
|
||||||
|
|
||||||
|
/** Calls osgViewer::CompositeViewer::getFrameStamp() if we are using
|
||||||
|
composite viewer, otherwise osgViewer::Viewer::getFrameStamp(). */
|
||||||
|
osg::FrameStamp* getFrameStamp();
|
||||||
|
|
||||||
/** Get and set the manipulator object, if any.
|
/** Get and set the manipulator object, if any.
|
||||||
*/
|
*/
|
||||||
flightgear::FGEventHandler* getEventHandler() { return eventHandler.get(); }
|
flightgear::FGEventHandler* getEventHandler() { return eventHandler.get(); }
|
||||||
|
@ -84,7 +95,9 @@ public:
|
||||||
void setPlanes( double zNear, double zFar );
|
void setPlanes( double zNear, double zFar );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
int composite_viewer_enabled = -1;
|
||||||
osg::ref_ptr<osgViewer::Viewer> viewer;
|
osg::ref_ptr<osgViewer::Viewer> viewer;
|
||||||
|
osg::ref_ptr<osgViewer::CompositeViewer> composite_viewer;
|
||||||
osg::ref_ptr<flightgear::FGEventHandler> eventHandler;
|
osg::ref_ptr<flightgear::FGEventHandler> eventHandler;
|
||||||
|
|
||||||
osg::ref_ptr<osg::FrameStamp> _frameStamp;
|
osg::ref_ptr<osg::FrameStamp> _frameStamp;
|
||||||
|
|
|
@ -204,6 +204,12 @@ void SplashScreen::createNodes()
|
||||||
nullptr, -1.0, osg::Vec4(1.0, 0.0, 0.0, 1.0));
|
nullptr, -1.0, osg::Vec4(1.0, 0.0, 0.0, 1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fgGetBool("/sim/rendering/composite-viewer-enabled")) {
|
||||||
|
addText(geode, osg::Vec2(0.5f, 0.65f), 0.03,
|
||||||
|
"CompositeViewer",
|
||||||
|
osgText::Text::CENTER_CENTER,
|
||||||
|
nullptr, -1.0, osg::Vec4(1.0, 0.0, 0.0, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
|
|
||||||
|
|
1394
src/Viewer/sview.cxx
Normal file
1394
src/Viewer/sview.cxx
Normal file
File diff suppressed because it is too large
Load diff
80
src/Viewer/sview.hxx
Normal file
80
src/Viewer/sview.hxx
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
Support for extra view windows. Requires that composite-viewer is enabled at
|
||||||
|
startup with --composite-viewer=1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
||||||
|
|
||||||
|
#include <osgViewer/View>
|
||||||
|
|
||||||
|
|
||||||
|
/* Should be called before the first call to SviewCreate() so that
|
||||||
|
SviewCreate() can create new simgear::compositor::Compositor instances with the
|
||||||
|
same parameters as were used for the main window.
|
||||||
|
|
||||||
|
options
|
||||||
|
compositor_path
|
||||||
|
Suitable for passing to simgear::compositor::Compositor().
|
||||||
|
*/
|
||||||
|
void SViewSetCompositorParams(
|
||||||
|
osg::ref_ptr<simgear::SGReaderWriterOptions> options,
|
||||||
|
const std::string& compositor_path
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Pushes current main window view to internal circular list of two items used
|
||||||
|
by SviewCreate() with 'last_pair' or 'last_pair_double'. */
|
||||||
|
void SviewPush();
|
||||||
|
|
||||||
|
/* Updates camera position/orientation/zoom of all sviews - should be called
|
||||||
|
each frame. Will also handle closing of Sview windows. */
|
||||||
|
void SviewUpdate(double dt);
|
||||||
|
|
||||||
|
/* Deletes all internal views; e.g. used when restarting. */
|
||||||
|
void SviewClear();
|
||||||
|
|
||||||
|
/* A view, typically an extra view window. The definition of this is not
|
||||||
|
public. */
|
||||||
|
struct SviewView;
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is the main interface to the Sview system. We create a new SviewView in a
|
||||||
|
new top-level window. It will be updated as required by SviewUpdate().
|
||||||
|
|
||||||
|
As of 2020-11-18, the new window will be half width and height of the main
|
||||||
|
window, and will have top-left corner at (100, 100). It can be dragged, resized
|
||||||
|
and closed by the user.
|
||||||
|
|
||||||
|
type:
|
||||||
|
This controls what sort of view we create:
|
||||||
|
|
||||||
|
"current"
|
||||||
|
Clones the current view.
|
||||||
|
"last_pair"
|
||||||
|
Look from first pushed view's eye to second pushed view's eye. Returns
|
||||||
|
nullptr if SviewPush hasn't been called at least twice.
|
||||||
|
"last_pair_double"
|
||||||
|
Keep first pushed view's aircraft in foreground and second pushed
|
||||||
|
view's aircraft in background. Returns nullptr if SviewPush hasn't been
|
||||||
|
called at least twice.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Shared ptr to SviewView instance. As of 2020-11-18 there is little that
|
||||||
|
the caller can do with this. We handle closing of the SviewView's window
|
||||||
|
internally.
|
||||||
|
|
||||||
|
As of 2020-11-17, extra views have various limitations including:
|
||||||
|
|
||||||
|
No event handling, so no panning, zooming etc.
|
||||||
|
|
||||||
|
Tower View AGL is like Tower View so no zooming to keep ground visible.
|
||||||
|
|
||||||
|
Cockpit view has a incorrect calculation giving slightly incorrect
|
||||||
|
translation when rolling.
|
||||||
|
|
||||||
|
No damping in chase views.
|
||||||
|
|
||||||
|
Hard-coded chase distances.
|
||||||
|
*/
|
||||||
|
std::shared_ptr<SviewView> SviewCreate(const std::string& type);
|
|
@ -33,8 +33,12 @@
|
||||||
|
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
#include "view.hxx"
|
#include "view.hxx"
|
||||||
|
#include "sview.hxx"
|
||||||
|
#include "renderer.hxx"
|
||||||
|
|
||||||
#include "CameraGroup.hxx"
|
#include "CameraGroup.hxx"
|
||||||
|
#include "Scenery/scenery.hxx"
|
||||||
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
FGViewMgr::FGViewMgr(void)
|
FGViewMgr::FGViewMgr(void)
|
||||||
|
@ -134,6 +138,7 @@ FGViewMgr::unbind ()
|
||||||
_viewNumberProp.clear();
|
_viewNumberProp.clear();
|
||||||
|
|
||||||
ViewPropertyEvaluator::clear();
|
ViewPropertyEvaluator::clear();
|
||||||
|
SviewClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -155,6 +160,7 @@ FGViewMgr::update (double dt)
|
||||||
cameraGroup->update(toOsg(currentView->getViewPosition()),
|
cameraGroup->update(toOsg(currentView->getViewPosition()),
|
||||||
toOsg(currentView->getViewOrientation()));
|
toOsg(currentView->getViewOrientation()));
|
||||||
}
|
}
|
||||||
|
SviewUpdate(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGViewMgr::clear()
|
void FGViewMgr::clear()
|
||||||
|
@ -222,6 +228,33 @@ FGViewMgr::prev_view()
|
||||||
return get_current_view();
|
return get_current_view();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGViewMgr::view_push()
|
||||||
|
{
|
||||||
|
SviewPush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGViewMgr::clone_current_view()
|
||||||
|
{
|
||||||
|
clone_internal("current");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGViewMgr::clone_last_pair()
|
||||||
|
{
|
||||||
|
clone_internal("last_pair");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGViewMgr::clone_last_pair_double()
|
||||||
|
{
|
||||||
|
clone_internal("last_pair_double");
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
||||||
|
|
||||||
|
void FGViewMgr::clone_internal(const std::string& type)
|
||||||
|
{
|
||||||
|
SviewCreate(type);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FGViewMgr::add_view( flightgear::View * v )
|
FGViewMgr::add_view( flightgear::View * v )
|
||||||
{
|
{
|
||||||
|
|
|
@ -75,6 +75,19 @@ public:
|
||||||
flightgear::View* next_view();
|
flightgear::View* next_view();
|
||||||
flightgear::View* prev_view();
|
flightgear::View* prev_view();
|
||||||
|
|
||||||
|
//
|
||||||
|
void view_push();
|
||||||
|
|
||||||
|
// Experimental. Only works if --compositer-viewer=1 was specified. Creates
|
||||||
|
// new window with clone of current view. As of 2020-09-03, the clone's
|
||||||
|
// scenery is not displayed correctly.
|
||||||
|
void clone_current_view();
|
||||||
|
|
||||||
|
//
|
||||||
|
void clone_last_pair();
|
||||||
|
|
||||||
|
void clone_last_pair_double();
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
@ -84,6 +97,7 @@ private:
|
||||||
simgear::TiedPropertyList _tiedProperties;
|
simgear::TiedPropertyList _tiedProperties;
|
||||||
|
|
||||||
void setCurrentViewIndex(int newview);
|
void setCurrentViewIndex(int newview);
|
||||||
|
void clone_internal(const std::string& type);
|
||||||
|
|
||||||
bool _inited = false;
|
bool _inited = false;
|
||||||
std::vector<SGPropertyNode_ptr> config_list;
|
std::vector<SGPropertyNode_ptr> config_list;
|
||||||
|
|
|
@ -45,7 +45,7 @@ void initScenery()
|
||||||
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
|
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
|
||||||
FGRenderer* render = globals->get_renderer();
|
FGRenderer* render = globals->get_renderer();
|
||||||
render->init();
|
render->init();
|
||||||
render->setViewer(viewer.get());
|
render->setView(viewer.get());
|
||||||
|
|
||||||
// Start up the scenery subsystem.
|
// Start up the scenery subsystem.
|
||||||
globals->add_new_subsystem<FGScenery>(SGSubsystemMgr::DISPLAY);
|
globals->add_new_subsystem<FGScenery>(SGSubsystemMgr::DISPLAY);
|
||||||
|
|
Loading…
Add table
Reference in a new issue