From a124ddd5da1b05826375b91802cb951b3ef66e54 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 20 Mar 2016 22:51:37 +0100 Subject: [PATCH] LP-29 factorize dirty flag handling in new DirtySupport class simplifies OSGNode and OSGCameraManipulator OSGViewport should use DirtySupport too --- .../libs/osgearth/osgQtQuick/DirtySupport.cpp | 145 ++++++++++++++++++ .../libs/osgearth/osgQtQuick/DirtySupport.hpp | 63 ++++++++ .../libs/osgearth/osgQtQuick/OSGCamera.cpp | 7 +- .../osgQtQuick/OSGGeoTransformNode.cpp | 2 +- .../src/libs/osgearth/osgQtQuick/OSGNode.cpp | 81 ++-------- .../src/libs/osgearth/osgQtQuick/OSGNode.hpp | 10 +- .../osgearth/osgQtQuick/OSGTransformNode.cpp | 2 +- .../libs/osgearth/osgQtQuick/OSGViewport.cpp | 85 ++++------ .../libs/osgearth/osgQtQuick/OSGViewport.hpp | 2 +- .../osgQtQuick/ga/OSGCameraManipulator.cpp | 35 ++++- .../osgQtQuick/ga/OSGCameraManipulator.hpp | 6 + .../ga/OSGGeoTransformManipulator.cpp | 82 ++-------- .../ga/OSGGeoTransformManipulator.hpp | 6 +- ground/gcs/src/libs/osgearth/osgearth.pro | 2 + 14 files changed, 312 insertions(+), 216 deletions(-) create mode 100644 ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.cpp create mode 100644 ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.hpp diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.cpp new file mode 100644 index 000000000..11e2c4f43 --- /dev/null +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.cpp @@ -0,0 +1,145 @@ +/** + ****************************************************************************** + * + * @file DirtySupport.cpp + * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015. + * @addtogroup + * @{ + * @addtogroup + * @{ + * @brief + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "DirtySupport.hpp" + +#include +#include + +#include + +namespace osgQtQuick { +class Hidden; + +struct DirtySupport::NodeUpdateCallback : public osg::NodeCallback { +public: + NodeUpdateCallback(DirtySupport::Hidden *h) : h(h) + {} + + void operator()(osg::Node *node, osg::NodeVisitor *nv); + +private: + DirtySupport::Hidden *const h; +}; + +struct DirtySupport::Hidden { +private: + DirtySupport *const self; + + osg::ref_ptr nodeUpdateCallback; + + int dirtyFlags; + +public: + Hidden(DirtySupport *self) : self(self), dirtyFlags(0) + {} + + bool isDirty(int mask) const + { + return (dirtyFlags & mask) != 0; + } + + int dirty() const + { + return dirtyFlags; + } + + void setDirty(int mask) + { + if (!dirtyFlags) { + osg::Node *node = self->hookNode(); + if (node) { + if (!nodeUpdateCallback.valid()) { + // lazy creation + nodeUpdateCallback = new NodeUpdateCallback(this); + } + node->addUpdateCallback(nodeUpdateCallback.get()); + } else { + qWarning() << "DirtySupport::setDirty - node is null"; + } + } + dirtyFlags |= mask; + } + + void clearDirty() + { + osg::Node *node = self->hookNode(); + + if (node && nodeUpdateCallback.valid()) { + node->removeUpdateCallback(nodeUpdateCallback.get()); + } + dirtyFlags = 0; + } + + void update() + { + if (dirtyFlags) { + self->update(); + } + clearDirty(); + } +}; + +/* struct DirtySupport::NodeUpdateCallback */ + +void DirtySupport::NodeUpdateCallback::operator()(osg::Node *node, osg::NodeVisitor *nv) +{ + // qDebug() << "DirtySupport::NodeUpdateCallback"; + nv->traverse(*node); + h->update(); +} + +/* class DirtySupport */ + +DirtySupport::DirtySupport() : h(new Hidden(this)) +{} + +DirtySupport::~DirtySupport() +{ + delete h; +} + +int DirtySupport::dirty() const +{ + return h->dirty(); +} + +bool DirtySupport::isDirty(int mask) const +{ + return h->isDirty(mask); +} + +void DirtySupport::setDirty(int mask) +{ + h->setDirty(mask); +} + +void DirtySupport::clearDirty() +{ + h->clearDirty(); +} +} // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.hpp new file mode 100644 index 000000000..ace6c2ecc --- /dev/null +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.hpp @@ -0,0 +1,63 @@ +/** + ****************************************************************************** + * + * @file DirtySupport.hpp + * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015. + * @addtogroup + * @{ + * @addtogroup + * @{ + * @brief + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _H_OSGQTQUICK_DIRTYSUPPORT_H_ +#define _H_OSGQTQUICK_DIRTYSUPPORT_H_ + +namespace osg { +class Node; +} // namespace osg + +namespace osgQtQuick { +/** + * Provides support to: + * - manage dirty state flags + * - add/remove node callback to trigger refresh (compatible with viewer on demand mode) + */ +class DirtySupport { +public: + explicit DirtySupport(); + virtual ~DirtySupport(); + +protected: + int dirty() const; + bool isDirty(int mask = 0xFFFF) const; + void setDirty(int mask = 0xFFFF); + void clearDirty(); + +private: + struct Hidden; + struct NodeUpdateCallback; + Hidden *const h; + + virtual osg::Node *hookNode() const = 0; + + virtual void update() = 0; +}; +} // namespace osgQtQuick + +#endif // _H_OSGQTQUICK_DIRTYSUPPORT_H_ diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.cpp index 461db5205..0d5a40360 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.cpp @@ -100,9 +100,7 @@ public: qDebug() << "OSGCamera::updateClearColor - invalid camera"; return; } - - qDebug() << "OSGCamera::updateClearColor" << clearColor; - + // qDebug() << "OSGCamera::updateClearColor" << clearColor; camera->setClearColor(osg::Vec4(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF())); } @@ -145,11 +143,12 @@ public: void updateLogDepthBuffer() { - qDebug() << "OSGCamera::updateLogDepthBuffer" << logDepthBufferEnabled; if (!camera.valid()) { qWarning() << "OSGCamera::updateLogDepthBuffer - invalid camera"; return; } + // qDebug() << "OSGCamera::updateLogDepthBuffer" << logDepthBufferEnabled; + #ifdef USE_OSGEARTH // install log depth buffer if requested if (logDepthBufferEnabled && !logDepthBuffer) { diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp index 8ff0f73aa..267320f7d 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp @@ -144,7 +144,7 @@ public: void updatePosition() { - qDebug() << "OSGGeoTransformNode::updatePosition" << position; + // qDebug() << "OSGGeoTransformNode::updatePosition" << position; osgEarth::MapNode *mapNode = NULL; if (sceneNode && sceneNode->node()) { diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.cpp index 018ed7613..d7abad4c8 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.cpp @@ -27,27 +27,16 @@ #include "OSGNode.hpp" +#include "DirtySupport.hpp" + #include -#include #include namespace osgQtQuick { class OSGNode; -class Hidden; -struct OSGNode::NodeUpdateCallback : public osg::NodeCallback { -public: - NodeUpdateCallback(OSGNode::Hidden *h) : h(h) - {} - - void operator()(osg::Node *node, osg::NodeVisitor *nv); - -private: - OSGNode::Hidden *const h; -}; - -struct OSGNode::Hidden : public QObject { +struct OSGNode::Hidden : public QObject, public DirtySupport { Q_OBJECT friend class OSGNode; @@ -57,48 +46,20 @@ private: osg::ref_ptr node; - osg::ref_ptr nodeUpdateCallback; - bool complete; - int dirty; public: - Hidden(OSGNode *self) : QObject(self), self(self), complete(false), dirty(0) + Hidden(OSGNode *self) : QObject(self), self(self), complete(false) /*, dirty(0)*/ {} - bool isDirty(int mask) const + osg::Node *hookNode() const { - return (dirty & mask) != 0; - } - - void setDirty(int mask) - { - if (!dirty) { - if (node) { - if (!nodeUpdateCallback.valid()) { - // lazy creation - nodeUpdateCallback = new NodeUpdateCallback(this); - } - node->addUpdateCallback(nodeUpdateCallback.get()); - } - } - dirty |= mask; - } - - void clearDirty() - { - if (node && nodeUpdateCallback.valid()) { - node->removeUpdateCallback(nodeUpdateCallback.get()); - } - dirty = 0; + return self->node(); } void update() { - if (dirty) { - self->update(); - } - clearDirty(); + return self->update(); } bool acceptNode(osg::Node *aNode) @@ -106,32 +67,21 @@ public: if (node == aNode) { return false; } - if (node && dirty) { - node->setUpdateCallback(NULL); + + int flags = dirty(); + if (flags) { + clearDirty(); } node = aNode; if (node) { - if (dirty) { - if (!nodeUpdateCallback.valid()) { - // lazy creation - nodeUpdateCallback = new NodeUpdateCallback(this); - } - node->setUpdateCallback(nodeUpdateCallback); + if (flags) { + setDirty(flags); } } return true; } }; -/* struct OSGNode::NodeUpdateCallback */ - -void OSGNode::NodeUpdateCallback::operator()(osg::Node *node, osg::NodeVisitor *nv) -{ - // qDebug() << "OSGNode::NodeUpdateCallback"; - nv->traverse(*node); - h->update(); -} - /* class OSGNode */ OSGNode::OSGNode(QObject *parent) : QObject(parent), QQmlParserStatus(), h(new Hidden(this)) @@ -154,11 +104,6 @@ void OSGNode::setNode(osg::Node *node) } } -bool OSGNode::isDirty() const -{ - return h->isDirty(0xFFFFFFFF); -} - bool OSGNode::isDirty(int mask) const { return h->isDirty(mask); diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.hpp index 1f1764362..57448a2af 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.hpp @@ -40,7 +40,6 @@ * - 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). * @@ -55,9 +54,6 @@ class OSGQTQUICK_EXPORT OSGNode : public QObject, public QQmlParserStatus { Q_OBJECT Q_INTERFACES(QQmlParserStatus) - friend class OSGViewport; - friend class NodeUpdateCallback; - public: explicit OSGNode(QObject *parent = 0); virtual ~OSGNode(); @@ -66,9 +62,8 @@ public: void setNode(osg::Node *node); protected: - bool isDirty() const; - bool isDirty(int mask) const; - void setDirty(int mask); + bool isDirty(int mask = 0xFFFF) const; + void setDirty(int mask = 0xFFFF); void clearDirty(); void classBegin(); @@ -83,7 +78,6 @@ signals: private: struct Hidden; - struct NodeUpdateCallback; Hidden *const h; virtual void update(); diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.cpp index c0cf7a8b9..ad62d58ea 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.cpp @@ -102,7 +102,7 @@ public: void updateScale() { - qDebug() << "OSGTransformNode::updateScale" << scale; + // qDebug() << "OSGTransformNode::updateScale" << scale; if ((scale.x() != 0.0) || (scale.y() != 0.0) || (scale.z() != 0.0)) { transform->setScale(osg::Vec3d(scale.x(), scale.y(), scale.z())); // transform->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.cpp index 1104105c5..5e52e9d30 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.cpp @@ -72,7 +72,30 @@ which will separate the clip plane calculations of the helicopter from those of the earth. * TODO : add OSGView to handle multiple views for a given OSGViewport - */ +*/ + +/* + that's a typical error when working with high-resolution (retina) + displays. The issue here is that on the high-resolution devices, the UI + operates with a virtual pixel size that is smaller than the real number + of pixels on the device. For example, you get coordinates from 0 to 2048 + while the real device resolution if 4096 pixels. This factor has to be + taken into account when mapping from window coordinates to OpenGL, e.g., + when calling glViewport. + + How you can get this factor depends on the GUI library you are using. In + Qt, you can query it with QWindow::devicePixelRatio(): + http://doc.qt.io/qt-5/qwindow.html#devicePixelRatio + + So, there should be something like + glViewport(0, 0, window->width() * window->devicePixelRatio(), + window->height() * window->devicePixelRatio()). + + Also keep in mind that you have to do the same e.g. for mouse coordinates. + + I think osgQt already handles this correctly, so you shouldn't have to + worry about this if you use the classes provided by osgQt ... +*/ namespace osgQtQuick { enum DirtyFlag { Scene = 1 << 0, Camera = 1 << 1 }; @@ -93,7 +116,6 @@ private: osg::ref_ptr gc; - public: OSGNode *sceneNode; OSGCamera *cameraNode; @@ -483,12 +505,12 @@ public: osg::Viewport *viewport = h->view->getCamera()->getViewport(); if ((viewport->width() != item->width()) || (viewport->height() != item->height())) { - qDebug() << "*** RESIZE" << frameCount << viewport->width() << "x" << viewport->height() << "->" << item->width() << "x" << item->height(); + // qDebug() << "*** RESIZE" << frameCount << viewport->width() << "x" << viewport->height() << "->" << item->width() << "x" << item->height(); needToDoFrame = true; + // h->view->getCamera()->resize(item->width(), item->height()); int dpr = h->self->window()->devicePixelRatio(); h->view->getCamera()->getGraphicsContext()->resized(0, 0, item->width() * dpr, item->height() * dpr); - // h->view.get()->getEventQueue()->windowResize(0, 0, item->width() * dpr, item->height() * dpr); // trick to force a "home" on first few frames to absorb initial spurious resizes if (frameCount <= 2) { @@ -498,16 +520,11 @@ public: // refresh busy state h->self->setBusy(h->view->getDatabasePager()->getRequestsInProgress()); - // TODO also expose request list size to Qml if (h->view->getDatabasePager()->getFileRequestListSize() > 0) { // qDebug() << h->view->getDatabasePager()->getFileRequestListSize(); } - h->self->setBusy(h->view->getDatabasePager()->getRequestsInProgress()); - // TODO also expose request list size to Qml - // qDebug() << h->view->getDatabasePager()->getFileRequestListSize(); - if (!needToDoFrame) { needToDoFrame = h->viewer->checkNeedToDoFrame(); } @@ -520,31 +537,12 @@ public: } if (needToDoFrame) { // qDebug() << "ViewportRenderer::synchronize - update scene" << frameCount; - - // info(); h->viewer->advance(); h->viewer->eventTraversal(); h->viewer->updateTraversal(); } } - void info() - { - if (!h->view.valid()) { - return; - } - // If the database pager is going to update the scene the render flag is - // set so that the updates show up - qDebug() << "DatabasePager" << (h->view->getDatabasePager()->requiresUpdateSceneGraph() || h->view->getDatabasePager()->getRequestsInProgress()); - - // if there update callbacks then we need to do frame. - qDebug() << "Camera" << (h->view->getCamera()->getUpdateCallback()); - qDebug() << "Scene" << (h->view->getSceneData() && h->view->getSceneData()->getNumChildrenRequiringUpdateTraversal() > 0); - - // check if events are available and need processing - qDebug() << "Events" << (h->viewer->checkEvents()); - } - // This function is called when the FBO should be rendered into. // The framebuffer is bound at this point and the glViewport has been set up to match the FBO size. void render() @@ -581,34 +579,7 @@ public: format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); // format.setSamples(4); - /** - * that's a typical error when working with high-resolution (retina) - displays. The issue here is that on the high-resolution devices, the UI - operates with a virtual pixel size that is smaller than the real number - of pixels on the device. For example, you get coordinates from 0 to 2048 - while the real device resolution if 4096 pixels. This factor has to be - taken into account when mapping from window coordinates to OpenGL, e.g., - when calling glViewport. - - How you can get this factor depends on the GUI library you are using. In - Qt, you can query it with QWindow::devicePixelRatio(): - http://doc.qt.io/qt-5/qwindow.html#devicePixelRatio - - So, there should be something like - glViewport(0, 0, window->width() * window->devicePixelRatio(), - window->height() * window->devicePixelRatio()). - - Also keep in mind that you have to do the same e.g. for mouse coordinates. - - I think osgQt already handles this correctly, so you shouldn't have to - worry about this if you use the classes provided by osgQt ... - */ - // Keeping this for reference : - // Mac need(ed) to have devicePixelRatio (dpr) taken into account (i.e. dpr = 2). - // Further tests on Mac have shown that although dpr is still 2 it should not be used to scale the fbo. - // Note that getting the window to get the devicePixelRatio is not great (messing with windows is often a bad idea...) - int dpr = 1; // h->self->window()->devicePixelRatio(); - QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(size.width() / dpr, size.height() / dpr, format); + QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(size.width(), size.height(), format); return fbo; } @@ -731,7 +702,7 @@ QSGNode *OSGViewport::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode { // qDebug() << "OSGViewport::updatePaintNode"; if (!node) { - qDebug() << "OSGViewport::updatePaintNode - set transform"; + // qDebug() << "OSGViewport::updatePaintNode - set transform"; node = QQuickFramebufferObject::updatePaintNode(node, nodeData); QSGSimpleTextureNode *n = static_cast(node); return node; diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.hpp index 66fd8a342..e8b968c72 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.hpp @@ -57,9 +57,9 @@ class OSGQTQUICK_EXPORT OSGViewport : public QQuickFramebufferObject { Q_PROPERTY(osgQtQuick::UpdateMode::Enum updateMode READ updateMode WRITE setUpdateMode NOTIFY updateModeChanged) Q_PROPERTY(bool busy READ busy NOTIFY busyChanged) -public: friend class ViewportRenderer; +public: explicit OSGViewport(QQuickItem *parent = 0); virtual ~OSGViewport(); diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGCameraManipulator.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGCameraManipulator.cpp index 88badea24..6a381fe2e 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGCameraManipulator.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGCameraManipulator.cpp @@ -27,6 +27,7 @@ #include "OSGCameraManipulator.hpp" +#include "../DirtySupport.hpp" #include "../OSGNode.hpp" #include @@ -34,11 +35,13 @@ #include namespace osgQtQuick { -struct OSGCameraManipulator::Hidden : public QObject { +struct OSGCameraManipulator::Hidden : public QObject, public DirtySupport { Q_OBJECT + friend class OSGCameraManipulator; + private: - OSGCameraManipulator * const self; + OSGCameraManipulator *const self; public: osg::ref_ptr manipulator; @@ -52,6 +55,16 @@ public: ~Hidden() {} + osg::Node *hookNode() const + { + return manipulator->getNode(); + } + + void update() + { + return self->update(); + } + bool acceptSceneNode(OSGNode *node) { qDebug() << "OSGCameraManipulator::acceptSceneNode" << node; @@ -113,6 +126,21 @@ void OSGCameraManipulator::setSceneNode(OSGNode *node) } } +bool OSGCameraManipulator::isDirty(int mask) const +{ + return h->isDirty(mask); +} + +void OSGCameraManipulator::setDirty(int mask) +{ + h->setDirty(mask); +} + +void OSGCameraManipulator::clearDirty() +{ + h->clearDirty(); +} + void OSGCameraManipulator::classBegin() { // qDebug() << "OSGCameraManipulator::classBegin" << this; @@ -138,6 +166,9 @@ osgGA::CameraManipulator *OSGCameraManipulator::asCameraManipulator() const { return h->manipulator; } + +void OSGCameraManipulator::update() +{} } // namespace osgQtQuick #include "OSGCameraManipulator.moc" diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGCameraManipulator.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGCameraManipulator.hpp index a5f2c48af..cca9d726a 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGCameraManipulator.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGCameraManipulator.hpp @@ -59,6 +59,10 @@ signals: void sceneNodeChanged(OSGNode *node); protected: + bool isDirty(int mask = 0xFFFF) const; + void setDirty(int mask = 0xFFFF); + void clearDirty(); + void classBegin(); void componentComplete(); @@ -68,6 +72,8 @@ protected: private: struct Hidden; Hidden *const h; + + virtual void update(); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGGeoTransformManipulator.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGGeoTransformManipulator.cpp index f8c1470f9..5035bed02 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGGeoTransformManipulator.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGGeoTransformManipulator.cpp @@ -32,7 +32,6 @@ #include #include -#include #include #include @@ -96,30 +95,15 @@ private: osg::ref_ptr node; }; -struct OSGGeoTransformManipulator::NodeUpdateCallback : public osg::NodeCallback { -public: - NodeUpdateCallback(OSGGeoTransformManipulator::Hidden *h) : h(h) - {} - - void operator()(osg::Node *node, osg::NodeVisitor *nv); - -private: - OSGGeoTransformManipulator::Hidden *const h; -}; - struct OSGGeoTransformManipulator::Hidden : public QObject { Q_OBJECT private: OSGGeoTransformManipulator * const self; - osg::ref_ptr nodeUpdateCallback; - osg::Matrix cameraPosition; osg::Matrix cameraRotation; - bool dirty; - public: osg::ref_ptr manipulator; @@ -129,7 +113,7 @@ public: bool clampToTerrain; bool intoTerrain; - Hidden(OSGGeoTransformManipulator *self) : QObject(self), self(self), dirty(false), clampToTerrain(false), intoTerrain(false) + Hidden(OSGGeoTransformManipulator *self) : QObject(self), self(self), clampToTerrain(false), intoTerrain(false) { manipulator = new MyManipulator(); self->setManipulator(manipulator); @@ -138,45 +122,6 @@ public: ~Hidden() {} - // TODO factorize up - void setDirty() - { - if (dirty) { - return; - } - // qDebug() << "OSGGeoTransformManipulator::setDirty"; - dirty = true; - osg::Node *node = manipulator->getNode(); - if (node) { - if (!nodeUpdateCallback.valid()) { - // lazy creation - nodeUpdateCallback = new NodeUpdateCallback(this); - } - node->addUpdateCallback(nodeUpdateCallback.get()); - } else { - qWarning() << "OSGGeoTransformManipulator::setDirty - no node..."; - } - } - - // TODO factorize up - void clearDirty() - { - // qDebug() << "OSGGeoTransformManipulator::clearDirty"; - osg::Node *node = manipulator->getNode(); - - if (node && nodeUpdateCallback.valid()) { - node->removeUpdateCallback(nodeUpdateCallback.get()); - } - dirty = false; - } - - void update() - { - updatePosition(); - updateAttitude(); - updateManipulator(); - } - void updateManipulator() { // qDebug() << "OSGGeoTransformManipulator::updateManipulator"; @@ -256,16 +201,6 @@ void MyManipulator::updateCamera(osg::Camera & camera) CameraManipulator::updateCamera(camera); } -/* struct OSGGeoTransformManipulator::NodeUpdateCallback */ - -void OSGGeoTransformManipulator::NodeUpdateCallback::operator()(osg::Node *node, osg::NodeVisitor *nv) -{ - // qDebug() << "OSGGeoTransformManipulator::NodeUpdateCallback"; - nv->traverse(*node); - h->update(); - h->clearDirty(); -} - /* class OSGGeoTransformManipulator */ OSGGeoTransformManipulator::OSGGeoTransformManipulator(QObject *parent) : OSGCameraManipulator(parent), h(new Hidden(this)) @@ -304,7 +239,7 @@ void OSGGeoTransformManipulator::setAttitude(QVector3D arg) { if (h->attitude != arg) { h->attitude = arg; - h->setDirty(); + setDirty(); emit attitudeChanged(attitude()); } } @@ -318,7 +253,7 @@ void OSGGeoTransformManipulator::setPosition(QVector3D arg) { if (h->position != arg) { h->position = arg; - h->setDirty(); + setDirty(); emit positionChanged(position()); } } @@ -329,8 +264,15 @@ void OSGGeoTransformManipulator::componentComplete() OSGCameraManipulator::componentComplete(); qDebug() << "OSGGeoTransformManipulator::componentComplete" << this; - h->update(); - h->clearDirty(); + update(); + clearDirty(); +} + +void OSGGeoTransformManipulator::update() +{ + h->updatePosition(); + h->updateAttitude(); + h->updateManipulator(); } } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGGeoTransformManipulator.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGGeoTransformManipulator.hpp index 3a7ee129a..a8bdc52c9 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGGeoTransformManipulator.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/ga/OSGGeoTransformManipulator.hpp @@ -41,9 +41,6 @@ class OSGQTQUICK_EXPORT OSGGeoTransformManipulator : public OSGCameraManipulator Q_PROPERTY(bool clampToTerrain READ clampToTerrain WRITE setClampToTerrain NOTIFY clampToTerrainChanged) Q_PROPERTY(bool intoTerrain READ intoTerrain NOTIFY intoTerrainChanged) - friend class NodeUpdateCallback; - friend class MyManipulator; - public: explicit OSGGeoTransformManipulator(QObject *parent = 0); virtual ~OSGGeoTransformManipulator(); @@ -70,8 +67,9 @@ protected: private: struct Hidden; - struct NodeUpdateCallback; Hidden *const h; + + virtual void update(); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgearth.pro b/ground/gcs/src/libs/osgearth/osgearth.pro index 6969314cf..2a8205b8c 100644 --- a/ground/gcs/src/libs/osgearth/osgearth.pro +++ b/ground/gcs/src/libs/osgearth/osgearth.pro @@ -48,6 +48,7 @@ SOURCES += \ HEADERS += \ osgQtQuick/Export.hpp \ + osgQtQuick/DirtySupport.hpp \ osgQtQuick/OSGNode.hpp \ osgQtQuick/OSGGroup.hpp \ osgQtQuick/OSGTransformNode.hpp \ @@ -59,6 +60,7 @@ HEADERS += \ osgQtQuick/OSGViewport.hpp SOURCES += \ + osgQtQuick/DirtySupport.cpp \ osgQtQuick/OSGNode.cpp \ osgQtQuick/OSGGroup.cpp \ osgQtQuick/OSGTransformNode.cpp \