I wrote a sample application using OsgQtQuick that shows the Earth in two views:

with the following QML, that I copied from OsgQtQuick samples:
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
id: window
menuBar: MenuBar {
Menu {
title: qsTr("File")
MenuItem {
text: qsTr("&Open3")
iconSource: ":/images/Test32x32.png"
onTriggered: console.log("Open action triggered");
}
MenuItem {
text: qsTr("Exit")
onTriggered: Qt.quit();
}
}
}
OSG.Notify {
id: notifier
notifyLevel: OSG.Notify.WARN
onNotify: console.log(message);
}
OSGDB.Loader {
id: loader
objectName: "loader"
source: "file:///home/dmitry/examples/osgearth/tests/openstreetmap.earth"
onNodeChanged: {
console.log("loader.node: " + getNode())
leftView.cameraManipulator.home()
rightView.cameraManipulator.home()
}
onStatusChanged: {
switch(status)
{
case OSGDB.Loader.Null:
statusLabel.text = "";
break;
case OSGDB.Loader.Loading:
statusLabel.text = "Loading...";
break;
case OSGDB.Loader.Ready:
statusLabel.text = "Ready";
statusLabel.visible = false;
break;
case OSGDB.Loader.Error:
statusLabel.text = "Error";
break;
}
}
}
GridLayout {
columns: 2
rowSpacing: 2
columnSpacing: 2
anchors.fill: parent
anchors.margins: 2
OSGViewer.View {
id: leftView
objectName: "leftView"
Text {
text: "View 1"
color: "white"
anchors.bottom: parent.bottom
}
cameraManipulator: OSGEarthUtil.EarthManipulator {}
sceneData: loader
Layout.fillHeight: true
Layout.fillWidth: true
}
OSGViewer.View {
id: rightView
objectName: "rightView"
Text {
text: "View 2"
color: "white"
anchors.bottom: parent.bottom
}
cameraManipulator: OSGEarthUtil.EarthManipulator {}
sceneData: loader
Layout.fillHeight: true
Layout.fillWidth: true
}
}
Text {
id: statusLabel
text: "Starting..."
color: "white"
font.pointSize: 24
anchors {
centerIn: parent
horizontalCenter: parent.horizontalCenter
}
}
Text {
text: "Both view should be identical"
color: "white"
anchors {
top: parent.top
horizontalCenter: parent.horizontalCenter
}
}
// Component.onCompleted: {
// leftView.cameraManipulator.home()
// rightView.cameraManipulator.home()
// }
}
It loads the Earth file from QML and adds some polygon with an annotation over the map in C++:
#include <osg/Node>
#include <osgEarth/MapNode>
#include <osgEarthSymbology/LineSymbol>
#include <osgEarthAnnotation/LabelNode>
#include <osgEarthAnnotation/FeatureNode>
#include <osgEarthFeatures/Feature>
#include <osg/NodeQtQml>
#include <osgDB/LoaderQtQml>
void addAnnotation(osgEarth::MapNode * mapNode)
{
using namespace osgEarth;
using namespace osgEarth::Symbology;
using namespace osgEarth::Annotation;
using namespace osgEarth::Features;
auto root = mapNode;
// Group to hold all our annotation elements.
osg::Group* annoGroup = new osg::Group();
root->addChild( annoGroup );
// Make a group for labels
osg::Group* labelGroup = new osg::Group();
annoGroup->addChild( labelGroup );
// Style our labels:
Style labelStyle;
labelStyle.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_CENTER;
labelStyle.getOrCreate<TextSymbol>()->fill()->color() = Color::Yellow;
// A lat/long SRS for specifying points.
const SpatialReference* geoSRS = mapNode->getMapSRS()->getGeographicSRS();
// a box that follows lines of latitude (rhumb line interpolation, the default)
{
Geometry* geom = new Polygon();
geom->push_back( osg::Vec3d(0, 40, 0) );
geom->push_back( osg::Vec3d(-60, 40, 0) );
geom->push_back( osg::Vec3d(-60, 60, 0) );
geom->push_back( osg::Vec3d(0, 60, 0) );
Feature* feature = new Feature(geom, geoSRS);
feature->geoInterp() = GEOINTERP_RHUMB_LINE;
Style geomStyle;
geomStyle.getOrCreate<LineSymbol>()->stroke()->color() = Color::Cyan;
geomStyle.getOrCreate<LineSymbol>()->stroke()->width() = 5.0f;
geomStyle.getOrCreate<LineSymbol>()->tessellationSize() = 75000;
geomStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
geomStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU;
FeatureNode* fnode = new FeatureNode(mapNode, feature, geomStyle);
annoGroup->addChild( fnode );
labelGroup->addChild( new LabelNode(mapNode, GeoPoint(geoSRS,-30, 50), "Rhumb line polygon", labelStyle) );
}
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QApplication::setWindowIcon(QIcon(":/images/app.ico"));
QQmlApplicationEngine engine;
engine.addImportPath("/home/dmitry/examples/install/qml");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QObject * topObject = engine.rootObjects().value(0);
QQuickWindow * window = qobject_cast<QQuickWindow *>(topObject);
if (window != nullptr)
{
qDebug("Main window has been created successfully.");
osgDB::LoaderQtQml * loader = window->findChild<osgDB::LoaderQtQml *>("loader");
if (loader != nullptr)
{
qDebug("loader found!.");
QObject::connect(loader, &osgDB::LoaderQtQml::nodeChanged, &app, [](osg::NodeQtQml* qmlNode)
{
osg::Node * node = qmlNode->node();
qDebug() << "Node has been changed:" << node->className();
osgEarth::MapNode * mapNode = dynamic_cast<osgEarth::MapNode *>(node);
if (mapNode != nullptr)
{
qDebug() << "Map Node found!:";
addAnnotation(mapNode);
}
});
return app.exec();
}
else
{
qDebug("loader not found!.");
}
}
}
It works not quite correct, because if I rotate the Earth in a view so that the text label (annotation) becomes invisible, the Earth in other view becomes black. See video demonstrating this effect. OSG version is 3.4 and OsgEarth version is 2.8. It is noteworthy that the original OsgEarth sample osgearth_overlayviewer with the same nodes added over the map works fine:
#include <osg/Notify>
#include <osg/Depth>
#include <osg/LineWidth>
#include <osg/LineStipple>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgViewer/CompositeViewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgEarth/OverlayDecorator>
#include <osgEarth/MapNode>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/ExampleResources>
#include <osgEarthUtil/Controls>
#include <osgEarthSymbology/Color>
#include <osgEarthSymbology/LineSymbol>
#include <osgEarthAnnotation/LabelNode>
#include <osgEarthAnnotation/FeatureNode>
#include <osgEarthFeatures/Feature>
using namespace osgEarth::Util;
using namespace osgEarth::Util::Controls;
using namespace osgEarth::Symbology;
//------------------------------------------------------------------------
namespace
{
void addAnnotation(osgEarth::MapNode * mapNode)
{
using namespace osgEarth;
using namespace osgEarth::Symbology;
using namespace osgEarth::Annotation;
using namespace osgEarth::Features;
osg::Group * root = mapNode;
// Group to hold all our annotation elements.
osg::Group* annoGroup = new osg::Group();
root->addChild( annoGroup );
// Make a group for labels
osg::Group* labelGroup = new osg::Group();
annoGroup->addChild( labelGroup );
// Style our labels:
Style labelStyle;
labelStyle.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_CENTER;
labelStyle.getOrCreate<TextSymbol>()->fill()->color() = Color::Yellow;
// A lat/long SRS for specifying points.
const SpatialReference* geoSRS = mapNode->getMapSRS()->getGeographicSRS();
// a box that follows lines of latitude (rhumb line interpolation, the default)
{
Geometry* geom = new Polygon();
geom->push_back( osg::Vec3d(0, 40, 0) );
geom->push_back( osg::Vec3d(-60, 40, 0) );
geom->push_back( osg::Vec3d(-60, 60, 0) );
geom->push_back( osg::Vec3d(0, 60, 0) );
Feature* feature = new Feature(geom, geoSRS);
feature->geoInterp() = GEOINTERP_RHUMB_LINE;
Style geomStyle;
geomStyle.getOrCreate<LineSymbol>()->stroke()->color() = Color::Cyan;
geomStyle.getOrCreate<LineSymbol>()->stroke()->width() = 5.0f;
geomStyle.getOrCreate<LineSymbol>()->tessellationSize() = 75000;
geomStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
geomStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU;
FeatureNode* fnode = new FeatureNode(mapNode, feature, geomStyle);
annoGroup->addChild( fnode );
labelGroup->addChild( new LabelNode(mapNode, GeoPoint(geoSRS,-30, 50), "Rhumb line polygon", labelStyle) );
}
}
}
int main(int argc, char** argv)
{
osg::ArgumentParser arguments(&argc,argv);
osgViewer::CompositeViewer viewer(arguments);
viewer.setThreadingModel( osgViewer::CompositeViewer::SingleThreaded );
// query the screen size.
osg::GraphicsContext::ScreenIdentifier si;
si.readDISPLAY();
if ( si.displayNum < 0 ) si.displayNum = 0; osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); unsigned width, height; wsi->getScreenResolution( si, width, height );
unsigned b = 50;
osgViewer::View* mainView = new osgViewer::View();
mainView->getCamera()->setNearFarRatio(0.00002);
EarthManipulator* em = new EarthManipulator();
em->getSettings()->setMinMaxPitch(-90, 0);
mainView->setCameraManipulator( em );
//mainView->setUpViewInWindow( 50, 50, 600, 600 );
mainView->setUpViewInWindow( b, b, (width/2)-b*2, (height-b*4) );
viewer.addView( mainView );
osgViewer::View* overlayView = new osgViewer::View();
overlayView->getCamera()->setNearFarRatio(0.00002);
//overlayView->getCamera()->setProjectionMatrixAsOrtho2D(-1,1,-1,1);
overlayView->setCameraManipulator( new EarthManipulator() );
//overlayView->setUpViewInWindow( 700, 50, 600, 600 );
overlayView->setUpViewInWindow( (width/2), b, (width/2)-b*2, (height-b*4) );
//overlayView->addEventHandler(new osgGA::StateSetManipulator(overlayView->getCamera()->getOrCreateStateSet()));
viewer.addView( overlayView );
std::string pathfile;
double animationSpeed = 1.0;
if (arguments.read("-p", pathfile))
{
mainView->setCameraManipulator( new osgGA::AnimationPathManipulator(pathfile) );
}
osg::Node* node = MapNodeHelper().load( arguments, mainView );
if ( node )
{
mainView->setSceneData( node );
MapNode* mapNode = MapNode::get(node);
OE_WARN << "Adding annotation." << std::endl; addAnnotation( mapNode ); //osg::Group* group = new osg::Group(); //group->addChild( mapNode );
overlayView->setSceneData( mapNode );
//setupOverlayView( overlayView, group, MapNode::get(node) );
return viewer.run();
}
else return -1;
}


Hello,
I’ve just come across this and was wondering if you found a solution?
I have this in an application I’m working on and haven’t had a chance to investigate it fully.
Thank,
Steve.