From 223d8f30e0dd964746cb94a4bbc8463a0dbdeb81 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Tue, 8 Mar 2016 03:29:00 +0100 Subject: [PATCH] LP-29 factorize update callback handling up into OSGNode allows "on demand" mode to work which can drastically reduce cpu usage in some cases --- .../osgearth/osgQtQuick/OSGBackgroundNode.cpp | 1 + .../libs/osgearth/osgQtQuick/OSGCamera.cpp | 188 ++++++------------ .../libs/osgearth/osgQtQuick/OSGCamera.hpp | 24 +-- .../libs/osgearth/osgQtQuick/OSGFileNode.cpp | 3 +- .../osgQtQuick/OSGGeoTransformNode.cpp | 58 ++---- .../osgQtQuick/OSGGeoTransformNode.hpp | 4 +- .../src/libs/osgearth/osgQtQuick/OSGGroup.cpp | 7 +- .../src/libs/osgearth/osgQtQuick/OSGNode.cpp | 134 ++++++++++++- .../src/libs/osgearth/osgQtQuick/OSGNode.hpp | 22 ++ .../libs/osgearth/osgQtQuick/OSGShapeNode.cpp | 3 +- .../libs/osgearth/osgQtQuick/OSGSkyNode.cpp | 4 +- .../libs/osgearth/osgQtQuick/OSGTextNode.cpp | 4 +- .../osgearth/osgQtQuick/OSGTransformNode.cpp | 52 ++--- .../osgearth/osgQtQuick/OSGTransformNode.hpp | 2 + .../libs/osgearth/osgQtQuick/OSGViewport.cpp | 39 ++-- ground/gcs/src/libs/osgearth/utility.cpp | 1 + .../src/share/qml/model/ModelTerrainView.qml | 2 +- ground/gcs/src/share/qml/model/ModelView.qml | 2 +- .../gcs/src/share/qml/pfd/PfdTerrainView.qml | 2 +- 19 files changed, 291 insertions(+), 261 deletions(-) diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGBackgroundNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGBackgroundNode.cpp index 0d624b9d6..a2683637f 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGBackgroundNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGBackgroundNode.cpp @@ -100,6 +100,7 @@ OSGBackgroundNode::OSGBackgroundNode(QObject *parent) : OSGNode(parent), h(new H OSGBackgroundNode::~OSGBackgroundNode() { // qDebug() << "OSGBackgroundNode::~OSGBackgroundNode"; + delete h; } const QUrl OSGBackgroundNode::imageFile() const diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.cpp index 692d853bb..02475e242 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.cpp @@ -54,29 +54,14 @@ namespace osgQtQuick { struct OSGCamera::Hidden : public QObject { Q_OBJECT - struct CameraUpdateCallback : public osg::NodeCallback { -public: - CameraUpdateCallback(Hidden *h) : h(h) {} - - void operator()(osg::Node *node, osg::NodeVisitor *nv); - - mutable Hidden *h; - }; - friend class CameraUpdateCallback; - public: - Hidden(OSGCamera *parent) : - QObject(parent), sceneData(NULL), manipulatorMode(ManipulatorMode::Default), node(NULL), - trackerMode(TrackerMode::NodeCenterAndAzim), trackNode(NULL), - logDepthBufferEnabled(false), clampToTerrain(false) + Hidden(OSGCamera *camera) : + QObject(camera), self(camera), sceneNode(NULL), + manipulatorMode(ManipulatorMode::Default), trackerMode(TrackerMode::NodeCenterAndAzim), trackNode(NULL), + logDepthBufferEnabled(false), clampToTerrain(false), intoTerrain(false) { - fieldOfView = 90.0; - - first = true; - - dirty = false; - fovDirty = false; + fieldOfView = 90.0; #ifdef USE_OSGEARTH logDepthBuffer = NULL; @@ -93,21 +78,21 @@ public: #endif } - bool acceptSceneData(OSGNode *node) + bool acceptSceneNode(OSGNode *node) { - qDebug() << "OSGCamera::acceptSceneData" << node; - if (sceneData == node) { + qDebug() << "OSGCamera::acceptSceneNode" << node; + if (sceneNode == node) { return true; } - if (sceneData) { - disconnect(sceneData); + if (sceneNode) { + disconnect(sceneNode); } - sceneData = node; + sceneNode = node; - if (sceneData) { - // connect(sceneData, &OSGNode::nodeChanged, this, &Hidden::onSceneDataChanged); + if (sceneNode) { + connect(sceneNode, &OSGNode::nodeChanged, this, &Hidden::onSceneNodeChanged); } return true; @@ -125,26 +110,6 @@ public: return true; } - bool acceptNode(OSGNode *node) - { - qDebug() << "OSGCamera::acceptNode" << node; - if (this->node == node) { - return false; - } - - if (this->node) { - disconnect(this->node); - } - - this->node = node; - - if (this->node) { - connect(this->node, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onNodeChanged(osg::Node *))); - } - - return true; - } - bool acceptTrackNode(OSGNode *node) { qDebug() << "OSGCamera::acceptTrackNode" << node; @@ -170,12 +135,7 @@ public: qDebug() << "OSGCamera::attach" << camera; this->camera = camera; - - // TODO don't add update callback as this disables ON_DEMAND frame update scheme - // see https://github.com/gwaldron/osgearth/commit/796daf4792ccaf18ae7eb6a5cb268eef0d42888d - // see ViewportRenderer::render() in OSGViewport.cpp - cameraUpdateCallback = new CameraUpdateCallback(this); - camera->addUpdateCallback(cameraUpdateCallback); + self->setNode(this->camera.get()); #ifdef USE_OSGEARTH // install log depth buffer if requested @@ -187,9 +147,7 @@ public: } #endif - dirty = true; - fovDirty = true; - updateCamera(); + updateFieldOfView(); updateAspectRatio(); } @@ -203,11 +161,6 @@ public: } this->camera = NULL; - if (cameraUpdateCallback.valid()) { - camera->removeUpdateCallback(cameraUpdateCallback); - cameraUpdateCallback = NULL; - } - #ifdef USE_OSGEARTH if (logDepthBuffer) { logDepthBuffer->uninstall(camera); @@ -283,11 +236,11 @@ public: } view->setCameraManipulator(cm, false); - if (cm && node && node->node()) { - qDebug() << "OSGCamera::attachManipulator - camera node" << node; + if (cm && sceneNode && sceneNode->node()) { + qDebug() << "OSGCamera::attachManipulator - camera node" << sceneNode; // set node used to auto compute home position // needs to be done after setting the manipulator on the view as the view will set its scene as the node - cm->setNode(node->node()); + cm->setNode(sceneNode->node()); } if (cm) { view->home(); @@ -301,21 +254,8 @@ public: view->setCameraManipulator(NULL, false); } - void updateCamera() + void updateFieldOfView() { - updateCameraFOV(); - if (manipulatorMode == ManipulatorMode::User) { - updateCameraPosition(); - } - } - - void updateCameraFOV() - { - if (!fovDirty || !camera.valid()) { - return; - } - fovDirty = false; - qDebug() << "OSGCamera::updateCameraFOV" << fieldOfView; double fovy, ar, zn, zf; @@ -337,13 +277,11 @@ public: camera->setProjectionMatrixAsPerspective(fovy, ar, zn, zf); } - void updateCameraPosition() + void updatePosition() { - if (!dirty || !camera.valid()) { + if (manipulatorMode != ManipulatorMode::User) { return; } - dirty = false; - // Altitude mode is absolute (absolute height above MSL/HAE) // HAE : Height above ellipsoid. This is the default. // MSL : Height above Mean Sea Level (MSL) if a geoid separation value is specified. @@ -357,8 +295,8 @@ public: #ifdef USE_OSGEARTH osgEarth::GeoPoint geoPoint = osgQtQuick::toGeoPoint(position); if (clampToTerrain) { - if (sceneData) { - osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneData->node()); + if (sceneNode) { + osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneNode->node()); if (mapNode) { intoTerrain = clampGeoPoint(geoPoint, 0.5f, mapNode); } else { @@ -391,18 +329,18 @@ public: camera->setViewMatrix(cameraMatrix); } - qreal fieldOfView; - bool fovDirty; + OSGCamera *const self; - OSGNode *sceneData; + osg::ref_ptr camera; + + qreal fieldOfView; + + OSGNode *sceneNode; ManipulatorMode::Enum manipulatorMode; - // to compute home position - OSGNode *node; - // for NodeTrackerManipulator - TrackerMode::Enum trackerMode; + TrackerMode::Enum trackerMode; OSGNode *trackNode; bool logDepthBufferEnabled; @@ -410,25 +348,17 @@ public: osgEarth::Util::LogarithmicDepthBuffer *logDepthBuffer; #endif - bool first; - - // for User manipulator - bool dirty; - bool clampToTerrain; bool intoTerrain; QVector3D attitude; QVector3D position; - osg::ref_ptr camera; - osg::ref_ptr cameraUpdateCallback; - private slots: - void onNodeChanged(osg::Node *node) + void onSceneNodeChanged(osg::Node *node) { - qDebug() << "OSGCamera::onNodeChanged" << node; - qWarning() << "OSGCamera::onNodeChanged - needs to be implemented"; + qDebug() << "OSGCamera::onSceneNodeChanged" << node; + qWarning() << "OSGCamera::onSceneNodeChanged - needs to be implemented"; } void onTrackNodeChanged(osg::Node *node) @@ -438,16 +368,9 @@ private slots: } }; -/* struct Hidden::CameraUpdateCallback */ - -void OSGCamera::Hidden::CameraUpdateCallback::operator()(osg::Node *node, osg::NodeVisitor *nv) -{ - h->updateCamera(); -} - /* class OSGCamera */ -OSGCamera::OSGCamera(QObject *parent) : QObject(parent), h(new Hidden(this)) +OSGCamera::OSGCamera(QObject *parent) : OSGNode(parent), h(new Hidden(this)) { qDebug() << "OSGCamera::OSGCamera"; } @@ -455,6 +378,7 @@ OSGCamera::OSGCamera(QObject *parent) : QObject(parent), h(new Hidden(this)) OSGCamera::~OSGCamera() { qDebug() << "OSGCamera::~OSGCamera"; + delete h; } qreal OSGCamera::fieldOfView() const @@ -467,20 +391,20 @@ void OSGCamera::setFieldOfView(qreal arg) { if (h->fieldOfView != arg) { h->fieldOfView = arg; - h->fovDirty = true; + setDirty(OSGCamera::FieldOfView); emit fieldOfViewChanged(fieldOfView()); } } -OSGNode *OSGCamera::sceneData() +OSGNode *OSGCamera::sceneNode() { - return h->sceneData; + return h->sceneNode; } -void OSGCamera::setSceneData(OSGNode *node) +void OSGCamera::setSceneNode(OSGNode *node) { - if (h->acceptSceneData(node)) { - emit sceneDataChanged(node); + if (h->acceptSceneNode(node)) { + emit sceneNodeChanged(node); } } @@ -496,18 +420,6 @@ void OSGCamera::setManipulatorMode(ManipulatorMode::Enum mode) } } -OSGNode *OSGCamera::node() const -{ - return h->node; -} - -void OSGCamera::setNode(OSGNode *node) -{ - if (h->acceptNode(node)) { - emit nodeChanged(node); - } -} - OSGNode *OSGCamera::trackNode() const { return h->trackNode; @@ -542,7 +454,7 @@ void OSGCamera::setClampToTerrain(bool arg) { if (h->clampToTerrain != arg) { h->clampToTerrain = arg; - h->dirty = true; + setDirty(OSGCamera::All); emit clampToTerrainChanged(clampToTerrain()); } } @@ -561,7 +473,7 @@ void OSGCamera::setAttitude(QVector3D arg) { if (h->attitude != arg) { h->attitude = arg; - h->dirty = true; + setDirty(OSGCamera::Attitude); emit attitudeChanged(attitude()); } } @@ -575,7 +487,7 @@ void OSGCamera::setPosition(QVector3D arg) { if (h->position != arg) { h->position = arg; - h->dirty = true; + setDirty(OSGCamera::Position); emit positionChanged(position()); } } @@ -593,6 +505,18 @@ void OSGCamera::setLogarithmicDepthBuffer(bool enabled) } } +void OSGCamera::update() +{ + // h->updateAspectRatio(); + if (isDirty(OSGCamera::FieldOfView)) { + h->updateFieldOfView(); + } + if (isDirty(OSGCamera::Position) || isDirty(OSGCamera::Attitude) || isDirty(OSGCamera::All)) { + h->updatePosition(); + } +} + + void OSGCamera::attach(osgViewer::View *view) { h->attachCamera(view->getCamera()); diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.hpp index 9b072f877..5fa4e4246 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.hpp @@ -29,6 +29,7 @@ #define _H_OSGQTQUICK_OSGCAMERA_H_ #include "Export.hpp" +#include "OSGNode.hpp" #include #include @@ -38,8 +39,6 @@ class View; } namespace osgQtQuick { -class OSGNode; - class ManipulatorMode : public QObject { Q_OBJECT public: @@ -64,11 +63,10 @@ public: // TODO // - expose track mode // - provide good default distance and attitude for tracker camera -class OSGQTQUICK_EXPORT OSGCamera : public QObject { +class OSGQTQUICK_EXPORT OSGCamera : public OSGNode { Q_OBJECT Q_PROPERTY(qreal fieldOfView READ fieldOfView WRITE setFieldOfView NOTIFY fieldOfViewChanged) - Q_PROPERTY(osgQtQuick::OSGNode * sceneData READ sceneData WRITE setSceneData NOTIFY sceneDataChanged) + Q_PROPERTY(osgQtQuick::OSGNode * sceneNode READ sceneNode WRITE setSceneNode NOTIFY sceneNodeChanged) Q_PROPERTY(osgQtQuick::ManipulatorMode::Enum manipulatorMode READ manipulatorMode WRITE setManipulatorMode NOTIFY manipulatorModeChanged) - Q_PROPERTY(osgQtQuick::OSGNode * node READ node WRITE setNode NOTIFY nodeChanged) Q_PROPERTY(osgQtQuick::OSGNode * trackNode READ trackNode WRITE setTrackNode NOTIFY trackNodeChanged) Q_PROPERTY(osgQtQuick::TrackerMode::Enum trackerMode READ trackerMode WRITE setTrackerMode NOTIFY trackerModeChanged) Q_PROPERTY(bool clampToTerrain READ clampToTerrain WRITE setClampToTerrain NOTIFY clampToTerrainChanged) @@ -77,6 +75,9 @@ class OSGQTQUICK_EXPORT OSGCamera : public QObject { Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged) Q_PROPERTY(bool logarithmicDepthBuffer READ logarithmicDepthBuffer WRITE setLogarithmicDepthBuffer NOTIFY logarithmicDepthBufferChanged) + enum DirtyFlag { Position, Attitude, FieldOfView, All }; + + public: explicit OSGCamera(QObject *parent = 0); virtual ~OSGCamera(); @@ -88,15 +89,12 @@ public: qreal fieldOfView() const; void setFieldOfView(qreal arg); - OSGNode *sceneData(); - void setSceneData(OSGNode *node); + OSGNode *sceneNode(); + void setSceneNode(OSGNode *node); ManipulatorMode::Enum manipulatorMode() const; void setManipulatorMode(ManipulatorMode::Enum); - OSGNode *node() const; - void setNode(OSGNode *node); - OSGNode *trackNode() const; void setTrackNode(OSGNode *node); @@ -123,12 +121,10 @@ public: signals: void fieldOfViewChanged(qreal arg); - void sceneDataChanged(OSGNode *node); + void sceneNodeChanged(OSGNode *node); void manipulatorModeChanged(ManipulatorMode::Enum); - void nodeChanged(OSGNode *node); - void trackNodeChanged(OSGNode *node); void trackerModeChanged(TrackerMode::Enum); @@ -143,6 +139,8 @@ signals: private: struct Hidden; Hidden *h; + + void update(); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGFileNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGFileNode.cpp index 19e5ff249..e210532c4 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGFileNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGFileNode.cpp @@ -75,7 +75,7 @@ private: OSGFileNode * const self; public: - Hidden(OSGFileNode *parent) : QObject(parent), self(parent), url(), async(false), optimizeMode(OptimizeMode::None) {} + Hidden(OSGFileNode *node) : QObject(node), self(node), url(), async(false), optimizeMode(OptimizeMode::None) {} bool acceptSource(QUrl url) { @@ -157,6 +157,7 @@ OSGFileNode::OSGFileNode(QObject *parent) : OSGNode(parent), h(new Hidden(this)) OSGFileNode::~OSGFileNode() { qDebug() << "OSGFileNode::~OSGFileNode"; + delete h; } const QUrl OSGFileNode::source() const diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp index 5905d07d3..a287141d1 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp @@ -1,7 +1,7 @@ /** ****************************************************************************** * - * @file OSGTransformNode.cpp + * @file OSGGeoTransformNode.cpp * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015. * @addtogroup * @{ @@ -41,22 +41,9 @@ namespace osgQtQuick { struct OSGGeoTransformNode::Hidden : public QObject { Q_OBJECT - struct NodeUpdateCallback : public osg::NodeCallback { -public: - NodeUpdateCallback(Hidden *h) : h(h) {} - - void operator()(osg::Node *node, osg::NodeVisitor *nv); - - mutable Hidden *h; - }; - friend class NodeUpdateCallback; - public: - Hidden(OSGGeoTransformNode *parent) : QObject(parent), self(parent), childNode(NULL), sceneNode(NULL), offset(-1.0), clampToTerrain(false), intoTerrain(false), dirty(false) - {} - - ~Hidden() + Hidden(OSGGeoTransformNode *node) : QObject(node), self(node), childNode(NULL), sceneNode(NULL), offset(-1.0), clampToTerrain(false), intoTerrain(false) {} bool acceptChildNode(OSGNode *node) @@ -71,7 +58,6 @@ public: } childNode = node; - dirty = true; if (childNode) { connect(childNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onChildNodeChanged(osg::Node *))); @@ -92,7 +78,6 @@ public: } sceneNode = node; - dirty = true; if (sceneNode) { connect(sceneNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onSceneNodeChanged(osg::Node *))); @@ -103,11 +88,6 @@ public: void updateNode() { - if (!dirty) { - return; - } - dirty = false; - // qDebug() << "OSGGeoTransformNode::updateNode" << this; osgEarth::GeoTransform *transform = getOrCreateTransform(); @@ -168,8 +148,6 @@ public: transform = new osgEarth::GeoTransform(); transform->setAutoRecomputeHeights(true); - transform->addUpdateCallback(new NodeUpdateCallback(this)); - self->setNode(transform); return transform.get(); @@ -177,11 +155,11 @@ public: OSGGeoTransformNode *const self; - OSGNode *childNode; - OSGNode *sceneNode; - osg::ref_ptr transform; + OSGNode *childNode; + OSGNode *sceneNode; + float offset; bool clampToTerrain; @@ -189,31 +167,21 @@ public: QVector3D position; - bool dirty; - private slots: void onChildNodeChanged(osg::Node *node) { qDebug() << "OSGGeoTransformNode::onChildNodeChanged" << node; - dirty = true; + self->setDirty(); } void onSceneNodeChanged(osg::Node *node) { qDebug() << "OSGGeoTransformNode::onSceneNodeChanged" << node; - dirty = true; + self->setDirty(); } }; -/* struct Hidden::NodeUpdateCallback */ - -void OSGGeoTransformNode::Hidden::NodeUpdateCallback::operator()(osg::Node *node, osg::NodeVisitor *nv) -{ - nv->traverse(*node); - h->updateNode(); -} - OSGGeoTransformNode::OSGGeoTransformNode(QObject *parent) : OSGNode(parent), h(new Hidden(this)) { qDebug() << "OSGGeoTransformNode::OSGGeoTransformNode"; @@ -222,6 +190,7 @@ OSGGeoTransformNode::OSGGeoTransformNode(QObject *parent) : OSGNode(parent), h(n OSGGeoTransformNode::~OSGGeoTransformNode() { qDebug() << "OSGGeoTransformNode::~OSGGeoTransformNode"; + delete h; } OSGNode *OSGGeoTransformNode::modelData() @@ -257,7 +226,7 @@ void OSGGeoTransformNode::setClampToTerrain(bool arg) { if (h->clampToTerrain != arg) { h->clampToTerrain = arg; - h->dirty = true; + setDirty(); emit clampToTerrainChanged(clampToTerrain()); } } @@ -276,18 +245,23 @@ void OSGGeoTransformNode::setPosition(QVector3D arg) { if (h->position != arg) { h->position = arg; - h->dirty = true; + setDirty(); emit positionChanged(position()); } } +void OSGGeoTransformNode::update() +{ + h->updateNode(); +} + void OSGGeoTransformNode::attach(osgViewer::View *view) { // qDebug() << "OSGGeoTransformNode::attach " << view; if (h->childNode) { h->childNode->attach(view); } - h->updateNode(); + update(); } void OSGGeoTransformNode::detach(osgViewer::View *view) diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.hpp index f3ba740fd..6f9a5a6ea 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.hpp @@ -1,7 +1,7 @@ /** ****************************************************************************** * - * @file OSGTransformNode.hpp + * @file OSGGeoTransformNode.hpp * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015. * @addtogroup * @{ @@ -81,6 +81,8 @@ signals: private: struct Hidden; Hidden *h; + + virtual void update(); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGroup.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGroup.cpp index 792fe3c40..fb7cb8ea7 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGroup.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGroup.cpp @@ -37,10 +37,8 @@ struct OSGGroup::Hidden : public QObject { Q_OBJECT public: - Hidden(OSGGroup *parent) : QObject(parent), self(parent) - { - group = new osg::Group; - } + Hidden(OSGGroup *node) : QObject(node), self(node), group(new osg::Group) + {} OSGGroup *self; @@ -135,6 +133,7 @@ OSGGroup::OSGGroup(QObject *parent) : OSGGroup::~OSGGroup() { qDebug() << "OSGGroup::~OSGGroup"; + delete h; } QQmlListProperty OSGGroup::children() diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.cpp index 7dc478af0..01c99d82f 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.cpp @@ -28,15 +28,118 @@ #include "OSGNode.hpp" #include +#include -#include +#include namespace osgQtQuick { -struct OSGNode::Hidden { - osg::ref_ptr node; +class OSGNode; +class Hidden; + +struct NodeUpdateCallback : public osg::NodeCallback { +public: + NodeUpdateCallback(OSGNode::Hidden *h) : h(h) {} + + void operator()(osg::Node *node, osg::NodeVisitor *nv); + +private: + OSGNode::Hidden *const h; }; -OSGNode::OSGNode(QObject *parent) : QObject(parent), h(new Hidden) + +struct OSGNode::Hidden /*: public QObject*/ { + // Q_OBJECT + + friend class OSGNode; +public: + Hidden(OSGNode *node) : /*QObject(node),*/ self(node), dirty(0) + {} + + bool isDirty(int flag) + { + return (dirty && (1 << flag)) != 0; + } + + void setDirty(int flag) + { + // qDebug() << "OSGNode::setDirty BEGIN"; + if (!dirty) { + if (node) { + if (!nodeUpdateCallback.valid()) { + // lazy creation + // qDebug() << "OSGNode::setDirty CREATE"; + nodeUpdateCallback = new NodeUpdateCallback(this); + } + // qDebug() << "OSGNode::setDirty ADD" << node; + node->setUpdateCallback(nodeUpdateCallback); + } + } + dirty |= 1 << flag; + // qDebug() << "OSGNode::setDirty DONE"; + } + + void clearDirty() + { + dirty = 0; + if (node && nodeUpdateCallback.valid()) { + // qDebug() << "OSGNode::clearDirty REMOVE CALLBACK"; + node->setUpdateCallback(NULL); + } + } + + void update() + { + // qDebug() << "OSGNode::update BEGIN"; + if (dirty) { + // qDebug() << "OSGNode::update UPDATE"; + self->update(); + } + clearDirty(); + // qDebug() << "OSGNode::update DONE"; + } + + bool acceptNode(osg::Node *aNode) + { + if (node == aNode) { + return false; + } + if (node && dirty) { + // qDebug() << "OSGNode::acceptNode REMOVE CALLBACK" << node; + node->setUpdateCallback(NULL); + } + node = aNode; + if (node) { + if (dirty) { + if (!nodeUpdateCallback.valid()) { + // lazy creation + // qDebug() << "OSGNode::acceptNode CREATE CALLBACK"; + nodeUpdateCallback = new NodeUpdateCallback(this); + } + // qDebug() << "OSGNode::acceptNode ADD CALLBACK"; + node->setUpdateCallback(nodeUpdateCallback); + } + } + return true; + } + +private: + OSGNode *const self; + + osg::ref_ptr node; + + osg::ref_ptr nodeUpdateCallback; + + int dirty; +}; + +void NodeUpdateCallback::operator()(osg::Node *node, osg::NodeVisitor *nv) +{ + // qDebug() << "NodeUpdateCallback::"; + nv->traverse(*node); + h->update(); +} + +OSGNode::OSGNode(QObject *parent) : QObject(parent), h(new Hidden(this)) {} OSGNode::~OSGNode() @@ -51,12 +154,31 @@ osg::Node *OSGNode::node() const void OSGNode::setNode(osg::Node *node) { - if (h->node.get() != node) { - h->node = node; + if (h->acceptNode(node)) { emit nodeChanged(node); } } +bool OSGNode::isDirty() +{ + return h->isDirty(1); +} + +bool OSGNode::isDirty(int flag) +{ + return h->isDirty(flag); +} + +void OSGNode::setDirty() +{ + h->setDirty(1); +} + +void OSGNode::setDirty(int flag) +{ + h->setDirty(flag); +} + void OSGNode::attach(osgViewer::View *view) {} diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.hpp index 47b91f963..bdfba4932 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.hpp @@ -32,6 +32,18 @@ #include +/** + * Only update() methods are allowed to update the OSG scenegraph. + * All other methods should call setDirty() which will later trigger an update. + * Exceptions: + * - node change events should be handled right away. + * + * Setting an OSGNode dirty will trigger the addition of a one time update callback. + * * + * This approach leads to some potential issues: + * - if a child sets a parent dirty, the parent will be updated later on the next update traversal (i.e. before the next frame). + * + */ namespace osg { class Node; } // namespace osg @@ -44,6 +56,8 @@ namespace osgQtQuick { class OSGQTQUICK_EXPORT OSGNode : public QObject { Q_OBJECT + friend class NodeUpdateCallback; + public: explicit OSGNode(QObject *parent = 0); virtual ~OSGNode(); @@ -54,12 +68,20 @@ public: virtual void attach(osgViewer::View *view); virtual void detach(osgViewer::View *view); +protected: + bool isDirty(); + bool isDirty(int flag); + void setDirty(); + void setDirty(int flag); + signals: void nodeChanged(osg::Node *node) const; private: struct Hidden; Hidden *h; + + virtual void update() {}; }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGShapeNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGShapeNode.cpp index 59567931a..a5b6246c7 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGShapeNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGShapeNode.cpp @@ -41,7 +41,7 @@ struct OSGShapeNode::Hidden : public QObject { Q_OBJECT public: - Hidden(OSGShapeNode *parent) : QObject(parent), self(parent), shapeType(ShapeType::Sphere) {} + Hidden(OSGShapeNode *node) : QObject(node), self(node), shapeType(ShapeType::Sphere) {} void realize() { @@ -97,6 +97,7 @@ OSGShapeNode::OSGShapeNode(QObject *parent) : OSGNode(parent), h(new Hidden(this OSGShapeNode::~OSGShapeNode() { qDebug() << "OSGShapeNode::~OSGShapeNode"; + delete h; } ShapeType::Enum OSGShapeNode::shapeType() const diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGSkyNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGSkyNode.cpp index 9dd3dc690..208c9f71f 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGSkyNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGSkyNode.cpp @@ -43,8 +43,7 @@ struct OSGSkyNode::Hidden : public QObject { Q_OBJECT public: - Hidden(OSGSkyNode *parent) : QObject(parent), - self(parent), sceneData(NULL), sunLightEnabled(true), minimumAmbientLight(0.03) + Hidden(OSGSkyNode *node) : QObject(node), self(node), sceneData(NULL), sunLightEnabled(true), minimumAmbientLight(0.03) { dateTime = QDateTime::currentDateTime(); } @@ -223,6 +222,7 @@ OSGSkyNode::OSGSkyNode(QObject *parent) : OSGNode(parent), h(new Hidden(this)) OSGSkyNode::~OSGSkyNode() { qDebug() << "OSGSkyNode::~OSGSkyNode"; + delete h; } OSGNode *OSGSkyNode::sceneData() diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTextNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTextNode.cpp index ac0fc18b9..f7016b3c0 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTextNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTextNode.cpp @@ -42,9 +42,7 @@ public: osg::ref_ptr text; }; -OSGTextNode::OSGTextNode(QObject *parent) : - osgQtQuick::OSGNode(parent), - h(new Hidden) +OSGTextNode::OSGTextNode(QObject *node) : OSGNode(node), h(new Hidden) { osg::ref_ptr textFont = createFont(QFont("Times")); diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.cpp index edf69e2ec..16ebe1c31 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.cpp @@ -37,22 +37,9 @@ namespace osgQtQuick { struct OSGTransformNode::Hidden : public QObject { Q_OBJECT - struct NodeUpdateCallback : public osg::NodeCallback { -public: - NodeUpdateCallback(Hidden *h) : h(h) {} - - void operator()(osg::Node *node, osg::NodeVisitor *nv); - - mutable Hidden *h; - }; - friend class NodeUpdateCallback; - public: - Hidden(OSGTransformNode *parent) : QObject(parent), self(parent), childNode(NULL), dirty(false) - {} - - ~Hidden() + Hidden(OSGTransformNode *node) : QObject(node), self(node), childNode(NULL) {} bool acceptChildNode(OSGNode *node) @@ -67,7 +54,6 @@ public: } childNode = node; - dirty = true; if (childNode) { connect(childNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onChildNodeChanged(osg::Node *))); @@ -78,11 +64,6 @@ public: void updateNode() { - if (!dirty) { - return; - } - dirty = false; - // qDebug() << "OSGTransformNode::updateNode" << this; osg::PositionAttitudeTransform *transform = getOrCreateTransform(); @@ -131,7 +112,6 @@ public: transform = new osg::PositionAttitudeTransform(); - transform->addUpdateCallback(new NodeUpdateCallback(this)); self->setNode(transform); @@ -140,33 +120,23 @@ public: OSGTransformNode *const self; - OSGNode *childNode; - osg::ref_ptr transform; + OSGNode *childNode; + QVector3D scale; QVector3D attitude; QVector3D position; - bool dirty; - private slots: void onChildNodeChanged(osg::Node *node) { qDebug() << "OSGTransformNode::onChildNodeChanged" << node; - dirty = true; + self->setDirty(); } }; -/* struct Hidden::NodeUpdateCallback */ - -void OSGTransformNode::Hidden::NodeUpdateCallback::operator()(osg::Node *node, osg::NodeVisitor *nv) -{ - nv->traverse(*node); - h->updateNode(); -} - OSGTransformNode::OSGTransformNode(QObject *parent) : OSGNode(parent), h(new Hidden(this)) { qDebug() << "OSGTransformNode::OSGTransformNode"; @@ -175,6 +145,7 @@ OSGTransformNode::OSGTransformNode(QObject *parent) : OSGNode(parent), h(new Hid OSGTransformNode::~OSGTransformNode() { qDebug() << "OSGTransformNode::~OSGTransformNode"; + delete h; } OSGNode *OSGTransformNode::modelData() @@ -198,7 +169,7 @@ void OSGTransformNode::setScale(QVector3D arg) { if (h->scale != arg) { h->scale = arg; - h->dirty = true; + setDirty(); emit scaleChanged(scale()); } } @@ -212,7 +183,7 @@ void OSGTransformNode::setAttitude(QVector3D arg) { if (h->attitude != arg) { h->attitude = arg; - h->dirty = true; + setDirty(); emit attitudeChanged(attitude()); } } @@ -226,18 +197,23 @@ void OSGTransformNode::setPosition(QVector3D arg) { if (h->position != arg) { h->position = arg; - h->dirty = true; + setDirty(); emit positionChanged(position()); } } +void OSGTransformNode::update() +{ + h->updateNode(); +} + void OSGTransformNode::attach(osgViewer::View *view) { // qDebug() << "OSGTransformNode::attach " << view; if (h->childNode) { h->childNode->attach(view); } - h->updateNode(); + update(); } void OSGTransformNode::detach(osgViewer::View *view) diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.hpp index d39320e15..aff685f2f 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.hpp @@ -73,6 +73,8 @@ signals: private: struct Hidden; Hidden *h; + + virtual void update(); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.cpp index e5eddb45d..a762e6bf2 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.cpp @@ -84,8 +84,8 @@ struct OSGViewport::Hidden : public QObject { public: - Hidden(OSGViewport *quickItem) : QObject(quickItem), - self(quickItem), + Hidden(OSGViewport *viewport) : QObject(viewport), + self(viewport), window(NULL), sceneData(NULL), camera(NULL), @@ -96,7 +96,7 @@ public: createViewer(); - connect(quickItem, &OSGViewport::windowChanged, this, &Hidden::onWindowChanged); + connect(self, &OSGViewport::windowChanged, this, &Hidden::onWindowChanged); } ~Hidden() @@ -493,20 +493,28 @@ public: return; } - needToDoFrame = h->viewer->checkNeedToDoFrame(); - if (needToDoFrame) { - if (firstFrame) { - h->view->init(); - if (!h->viewer->isRealized()) { - h->viewer->realize(); - } - firstFrame = false; - } - osg::Viewport *viewport = h->view->getCamera()->getViewport(); - if ((viewport->width() != item->width()) || (viewport->height() != item->height())) { - h->view->getCamera()->getGraphicsContext()->resized(0, 0, item->width(), item->height()); + if (firstFrame) { + h->view->init(); + if (!h->viewer->isRealized()) { + h->viewer->realize(); } + firstFrame = false; + } + needToDoFrame = false; + osg::Viewport *viewport = h->view->getCamera()->getViewport(); + if ((viewport->width() != item->width()) || (viewport->height() != item->height())) { + needToDoFrame = true; + h->view->getCamera()->getGraphicsContext()->resized(0, 0, item->width(), item->height()); + } + + if (!needToDoFrame) { + needToDoFrame = h->viewer->checkNeedToDoFrame(); + } + if (!needToDoFrame) { + needToDoFrame = !h->view->getEventQueue()->empty(); + } + if (needToDoFrame) { h->viewer->advance(); h->viewer->eventTraversal(); h->viewer->updateTraversal(); @@ -577,6 +585,7 @@ OSGViewport::OSGViewport(QQuickItem *parent) : QQuickFramebufferObject(parent), OSGViewport::~OSGViewport() { qDebug() << "OSGViewport::~OSGViewport"; + delete h; } UpdateMode::Enum OSGViewport::updateMode() const diff --git a/ground/gcs/src/libs/osgearth/utility.cpp b/ground/gcs/src/libs/osgearth/utility.cpp index 8f989ec25..a35f25cc9 100644 --- a/ground/gcs/src/libs/osgearth/utility.cpp +++ b/ground/gcs/src/libs/osgearth/utility.cpp @@ -444,6 +444,7 @@ QString getUsageString(osgViewer::CompositeViewer *viewer) osgEarth::GeoPoint toGeoPoint(const osgEarth::SpatialReference *srs, const QVector3D &position) { osgEarth::GeoPoint geoPoint(srs, position.x(), position.y(), position.z(), osgEarth::ALTMODE_ABSOLUTE); + return geoPoint; } diff --git a/ground/gcs/src/share/qml/model/ModelTerrainView.qml b/ground/gcs/src/share/qml/model/ModelTerrainView.qml index b4fb17b45..9f3fd0536 100644 --- a/ground/gcs/src/share/qml/model/ModelTerrainView.qml +++ b/ground/gcs/src/share/qml/model/ModelTerrainView.qml @@ -85,7 +85,7 @@ OSGViewport { logarithmicDepthBuffer: true manipulatorMode: ManipulatorMode.Track // use model to compute camera home position - node: modelTransformNode + sceneNode: modelTransformNode // model will be tracked trackNode: modelTransformNode } diff --git a/ground/gcs/src/share/qml/model/ModelView.qml b/ground/gcs/src/share/qml/model/ModelView.qml index 94e9292b2..68ea35ad5 100644 --- a/ground/gcs/src/share/qml/model/ModelView.qml +++ b/ground/gcs/src/share/qml/model/ModelView.qml @@ -60,7 +60,7 @@ Item { OSGCamera { id: camera fieldOfView: 90 - node: transformNode + sceneNode: transformNode } } diff --git a/ground/gcs/src/share/qml/pfd/PfdTerrainView.qml b/ground/gcs/src/share/qml/pfd/PfdTerrainView.qml index a9e8ffc15..57da2a4fb 100644 --- a/ground/gcs/src/share/qml/pfd/PfdTerrainView.qml +++ b/ground/gcs/src/share/qml/pfd/PfdTerrainView.qml @@ -57,7 +57,7 @@ OSGViewport { OSGCamera { id: camera fieldOfView: 100 - sceneData: terrainNode + sceneNode: terrainNode logarithmicDepthBuffer: true clampToTerrain: true manipulatorMode: ManipulatorMode.User