From 6c82a7f01ad71c5b308ea05d65ebe72082815b83 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Thu, 10 Mar 2016 21:14:01 +0100 Subject: [PATCH] LP-29 made code more consistent w/r to dirty handling, etc... --- .../osgearth/osgQtQuick/OSGBackgroundNode.cpp | 60 ++--- .../osgearth/osgQtQuick/OSGBackgroundNode.hpp | 5 + .../libs/osgearth/osgQtQuick/OSGCamera.cpp | 22 +- .../libs/osgearth/osgQtQuick/OSGCamera.hpp | 11 +- .../libs/osgearth/osgQtQuick/OSGFileNode.cpp | 140 ++++++----- .../libs/osgearth/osgQtQuick/OSGFileNode.hpp | 6 +- .../osgQtQuick/OSGGeoTransformNode.cpp | 137 ++++++----- .../osgQtQuick/OSGGeoTransformNode.hpp | 22 +- .../src/libs/osgearth/osgQtQuick/OSGGroup.cpp | 162 ++++++++----- .../src/libs/osgearth/osgQtQuick/OSGGroup.hpp | 8 +- .../src/libs/osgearth/osgQtQuick/OSGNode.cpp | 51 ++-- .../src/libs/osgearth/osgQtQuick/OSGNode.hpp | 23 +- .../libs/osgearth/osgQtQuick/OSGShapeNode.cpp | 62 ++--- .../libs/osgearth/osgQtQuick/OSGShapeNode.hpp | 5 + .../libs/osgearth/osgQtQuick/OSGSkyNode.cpp | 219 +++++++++--------- .../libs/osgearth/osgQtQuick/OSGSkyNode.hpp | 17 +- .../libs/osgearth/osgQtQuick/OSGTextNode.cpp | 125 ++++++---- .../libs/osgearth/osgQtQuick/OSGTextNode.hpp | 7 +- .../osgearth/osgQtQuick/OSGTransformNode.cpp | 111 +++++---- .../osgearth/osgQtQuick/OSGTransformNode.hpp | 14 +- .../libs/osgearth/osgQtQuick/OSGViewport.hpp | 10 +- 21 files changed, 709 insertions(+), 508 deletions(-) diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGBackgroundNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGBackgroundNode.cpp index a2683637f..48560d963 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGBackgroundNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGBackgroundNode.cpp @@ -38,30 +38,20 @@ namespace osgQtQuick { struct OSGBackgroundNode::Hidden : public QObject { Q_OBJECT +private: + OSGBackgroundNode * const self; + public: + QUrl url; + Hidden(OSGBackgroundNode *parent) : QObject(parent), self(parent), url() {} - bool acceptImageFile(QUrl url) + void updateNode() { - // qDebug() << "OSGBackgroundNode::acceptImageFile" << url; - if (this->url == url) { - return false; - } - - this->url = url; - - realize(); - - return true; - } - - void realize() - { - qDebug() << "OSGBackgroundNode::realize"; - - // qDebug() << "OSGBackgroundNode::realize - reading image file" << h->url.path(); + // qDebug() << "OSGBackgroundNode::realize - reading image file" << url.path(); osg::ref_ptr texture = new osg::Texture2D; - osg::ref_ptr image = osgDB::readImageFile(url.path().toStdString()); + osg::ref_ptr image = osgDB::readImageFile(url.path().toStdString()); + texture->setImage(image.get()); osg::ref_ptr quad = osg::createTexturedQuadGeometry( @@ -86,15 +76,15 @@ public: self->setNode(camera); } - - OSGBackgroundNode *const self; - - QUrl url; }; +/* class OSGBackgroundNode */ + +enum DirtyFlag { URL = 1 << 0 }; + OSGBackgroundNode::OSGBackgroundNode(QObject *parent) : OSGNode(parent), h(new Hidden(this)) { - // qDebug() << "OSGBackgroundNode::OSGBackgroundNode"; + qDebug() << "OSGBackgroundNode::OSGBackgroundNode"; } OSGBackgroundNode::~OSGBackgroundNode() @@ -111,10 +101,28 @@ const QUrl OSGBackgroundNode::imageFile() const void OSGBackgroundNode::setImageFile(const QUrl &url) { // qDebug() << "OSGBackgroundNode::setImageFile" << url; - if (h->acceptImageFile(url)) { - emit imageFileChanged(imageFile()); + if (h->url != url) { + h->url = url; + setDirty(URL); + emit imageFileChanged(url); } } + +void OSGBackgroundNode::update() +{ + if (isDirty(URL)) { + h->updateNode(); + } +} + +void OSGBackgroundNode::attach(osgViewer::View *view) +{ + update(); + clearDirty(); +} + +void OSGBackgroundNode::detach(osgViewer::View *view) +{} } // namespace osgQtQuick #include "OSGBackgroundNode.moc" diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGBackgroundNode.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGBackgroundNode.hpp index 01a21fdd3..746da7615 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGBackgroundNode.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGBackgroundNode.hpp @@ -53,6 +53,11 @@ signals: private: struct Hidden; Hidden *h; + + virtual void update(); + + virtual void attach(osgViewer::View *view); + virtual void detach(osgViewer::View *view); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.cpp index 02475e242..8c5b873f6 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.cpp @@ -55,7 +55,6 @@ struct OSGCamera::Hidden : public QObject { Q_OBJECT public: - Hidden(OSGCamera *camera) : QObject(camera), self(camera), sceneNode(NULL), manipulatorMode(ManipulatorMode::Default), trackerMode(TrackerMode::NodeCenterAndAzim), trackNode(NULL), @@ -333,6 +332,7 @@ public: osg::ref_ptr camera; + // Camera vertical field of view in degrees qreal fieldOfView; OSGNode *sceneNode; @@ -370,6 +370,8 @@ private slots: /* class OSGCamera */ +enum DirtyFlag { FieldOfView = 1 << 0, Position = 1 << 1, Attitude = 1 << 2 }; + OSGCamera::OSGCamera(QObject *parent) : OSGNode(parent), h(new Hidden(this)) { qDebug() << "OSGCamera::OSGCamera"; @@ -386,12 +388,11 @@ qreal OSGCamera::fieldOfView() const return h->fieldOfView; } -// Camera vertical field of view in degrees void OSGCamera::setFieldOfView(qreal arg) { if (h->fieldOfView != arg) { h->fieldOfView = arg; - setDirty(OSGCamera::FieldOfView); + setDirty(FieldOfView); emit fieldOfViewChanged(fieldOfView()); } } @@ -454,7 +455,6 @@ void OSGCamera::setClampToTerrain(bool arg) { if (h->clampToTerrain != arg) { h->clampToTerrain = arg; - setDirty(OSGCamera::All); emit clampToTerrainChanged(clampToTerrain()); } } @@ -473,7 +473,7 @@ void OSGCamera::setAttitude(QVector3D arg) { if (h->attitude != arg) { h->attitude = arg; - setDirty(OSGCamera::Attitude); + setDirty(Attitude); emit attitudeChanged(attitude()); } } @@ -487,7 +487,7 @@ void OSGCamera::setPosition(QVector3D arg) { if (h->position != arg) { h->position = arg; - setDirty(OSGCamera::Position); + setDirty(Position); emit positionChanged(position()); } } @@ -507,26 +507,26 @@ void OSGCamera::setLogarithmicDepthBuffer(bool enabled) void OSGCamera::update() { - // h->updateAspectRatio(); - if (isDirty(OSGCamera::FieldOfView)) { + if (isDirty(FieldOfView)) { h->updateFieldOfView(); } - if (isDirty(OSGCamera::Position) || isDirty(OSGCamera::Attitude) || isDirty(OSGCamera::All)) { + if (isDirty(Position | Attitude)) { h->updatePosition(); } } - void OSGCamera::attach(osgViewer::View *view) { h->attachCamera(view->getCamera()); h->attachManipulator(view); + update(); + clearDirty(); } void OSGCamera::detach(osgViewer::View *view) { - h->detachCamera(view->getCamera()); h->detachManipulator(view); + h->detachCamera(view->getCamera()); } } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.hpp index 5fa4e4246..48a2d4ace 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGCamera.hpp @@ -75,8 +75,7 @@ class OSGQTQUICK_EXPORT OSGCamera : public OSGNode { 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 }; - + friend class OSGViewport; public: explicit OSGCamera(QObject *parent = 0); @@ -115,9 +114,6 @@ public: bool logarithmicDepthBuffer(); void setLogarithmicDepthBuffer(bool enabled); - virtual void attach(osgViewer::View *view); - virtual void detach(osgViewer::View *view); - signals: void fieldOfViewChanged(qreal arg); @@ -140,7 +136,10 @@ private: struct Hidden; Hidden *h; - void update(); + virtual void update(); + + virtual void attach(osgViewer::View *view); + virtual void detach(osgViewer::View *view); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGFileNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGFileNode.cpp index e210532c4..a9ba9dba2 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGFileNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGFileNode.cpp @@ -45,10 +45,11 @@ public: void run() { - load(); + osg::Node *node = load(); + emit loaded(url, node); } - void load() + osg::Node *load() { QElapsedTimer t; @@ -57,8 +58,7 @@ public: // qDebug() << "OSGFileLoader - load - currentContext" << QOpenGLContext::currentContext(); osg::Node *node = osgDB::readNodeFile(url.path().toStdString()); // qDebug() << "OSGFileLoader::load - reading node" << node << "took" << t.elapsed() << "ms"; - - emit loaded(url, node); + return node; } signals: @@ -75,33 +75,37 @@ private: OSGFileNode * const self; public: - Hidden(OSGFileNode *node) : QObject(node), self(node), url(), async(false), optimizeMode(OptimizeMode::None) {} - - bool acceptSource(QUrl url) - { - // qDebug() << "OSGFileNode::acceptSource" << url; - - if (this->url == url) { - return false; - } - - this->url = url; - - if (url.isValid()) { - realize(); - } else { - qWarning() << "OSGFileNode::acceptNode - invalid url" << url; - self->setNode(NULL); - } - - return true; - } - - QUrl url; + QUrl source; bool async; OptimizeMode::Enum optimizeMode; + Hidden(OSGFileNode *node) : QObject(node), self(node), source(), async(false), optimizeMode(OptimizeMode::None) {} + + void updateNode() + { + // qDebug() << "OSGFileNode::updateNode" << source; + if (!source.isValid()) { + self->setNode(NULL); + if (!source.isEmpty()) { + qWarning() << "OSGFileNode::updateNode - invalid source" << source; + } + } + if (false /*async*/) { + // not supported yet + // it is not clear if thread safety is insured... + asyncLoad(source); + } else { + setNode(syncLoad(source)); + } + } + private: + osg::Node *syncLoad(const QUrl &url) + { + OSGFileLoader loader(url); + + return loader.load(); + } void asyncLoad(const QUrl &url) { @@ -112,64 +116,56 @@ private: loader->start(); } - void syncLoad(const QUrl &url) + void setNode(osg::Node *node) { - OSGFileLoader loader(url); - - connect(&loader, &OSGFileLoader::loaded, this, &Hidden::onLoaded); - loader.load(); - } - - void realize() - { - qDebug() << "OSGFileNode::realize"; - if (async) { - asyncLoad(url); - } else { - syncLoad(url); - } - } - - bool acceptNode(osg::Node *node) - { - qDebug() << "OSGFileNode::acceptNode" << node; + qDebug() << "OSGFileNode::setNode" << node; if (node && optimizeMode != OptimizeMode::None) { // qDebug() << "OSGFileNode::acceptNode - optimize" << node << optimizeMode; osgUtil::Optimizer optimizer; optimizer.optimize(node, osgUtil::Optimizer::DEFAULT_OPTIMIZATIONS); } self->setNode(node); - return true; } private slots: void onLoaded(const QUrl &url, osg::Node *node) { - acceptNode(node); + // called in async mode + // question : is it thread safe to call setNode() ? + // could calling setDirty help? is setDirty() thread safe ? + setNode(node); } }; +/* class OSGFileNode */ + +enum DirtyFlag { Source = 1 << 0, Async = 1 << 1, OptimizeMode = 1 << 2 }; + OSGFileNode::OSGFileNode(QObject *parent) : OSGNode(parent), h(new Hidden(this)) { qDebug() << "OSGFileNode::OSGFileNode"; + setAsync(false); + setOptimizeMode(OptimizeMode::None); } OSGFileNode::~OSGFileNode() { - qDebug() << "OSGFileNode::~OSGFileNode"; + // qDebug() << "OSGFileNode::~OSGFileNode"; delete h; } const QUrl OSGFileNode::source() const { - return h->url; + return h->source; } -void OSGFileNode::setSource(const QUrl &url) +void OSGFileNode::setSource(const QUrl &source) { - qDebug() << "OSGFileNode::setSource" << url; - if (h->acceptSource(url)) { - emit sourceChanged(source()); + qDebug() << "OSGFileNode::setSource" << source; + if (h->source != source) { + h->source = source; + setDirty(Source); + emit sourceChanged(source); } } @@ -183,6 +179,7 @@ void OSGFileNode::setAsync(const bool async) // qDebug() << "OSGFileNode::setAsync" << async; if (h->async != async) { h->async = async; + setDirty(Async); emit asyncChanged(async); } } @@ -192,14 +189,37 @@ OptimizeMode::Enum OSGFileNode::optimizeMode() const return h->optimizeMode; } -void OSGFileNode::setOptimizeMode(OptimizeMode::Enum mode) +void OSGFileNode::setOptimizeMode(OptimizeMode::Enum optimizeMode) { - // qDebug() << "OSGFileNode::setOptimizeMode" << mode; - if (h->optimizeMode != mode) { - h->optimizeMode = mode; - emit optimizeModeChanged(optimizeMode()); + // qDebug() << "OSGFileNode::setOptimizeMode" << optimizeMode; + if (h->optimizeMode != optimizeMode) { + h->optimizeMode = optimizeMode; + setDirty(OptimizeMode); + emit optimizeModeChanged(optimizeMode); } } + +void OSGFileNode::update() +{ + if (isDirty(Async)) { + // do nothing... + } + if (isDirty(OptimizeMode)) { + // TODO: trigger a node update ? + } + if (isDirty(Source)) { + h->updateNode(); + } +} + +void OSGFileNode::attach(osgViewer::View *view) +{ + update(); + clearDirty(); +} + +void OSGFileNode::detach(osgViewer::View *view) +{} } // namespace osgQtQuick #include "OSGFileNode.moc" diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGFileNode.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGFileNode.hpp index b0dbd2717..9ea870507 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGFileNode.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGFileNode.hpp @@ -50,7 +50,6 @@ class OSGQTQUICK_EXPORT OSGFileNode : public OSGNode { Q_PROPERTY(osgQtQuick::OptimizeMode::Enum optimizeMode READ optimizeMode WRITE setOptimizeMode NOTIFY optimizeModeChanged) public: - OSGFileNode(QObject *parent = 0); virtual ~OSGFileNode(); @@ -71,6 +70,11 @@ signals: private: struct Hidden; Hidden *h; + + virtual void update(); + + virtual void attach(osgViewer::View *view); + virtual void detach(osgViewer::View *view); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp index a287141d1..fdd1c09e7 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp @@ -41,10 +41,28 @@ namespace osgQtQuick { struct OSGGeoTransformNode::Hidden : public QObject { Q_OBJECT +private: + OSGGeoTransformNode * const self; + + osg::ref_ptr transform; + public: + OSGNode *childNode; + OSGNode *sceneNode; + + float offset; + + bool clampToTerrain; + bool intoTerrain; + + QVector3D position; Hidden(OSGGeoTransformNode *node) : QObject(node), self(node), childNode(NULL), sceneNode(NULL), offset(-1.0), clampToTerrain(false), intoTerrain(false) - {} + { + transform = new osgEarth::GeoTransform(); + transform->setAutoRecomputeHeights(true); + self->setNode(transform); + } bool acceptChildNode(OSGNode *node) { @@ -86,36 +104,51 @@ public: return true; } - void updateNode() + void updateTransformNode() { - // qDebug() << "OSGGeoTransformNode::updateNode" << this; - - osgEarth::GeoTransform *transform = getOrCreateTransform(); + bool updated = false; if (transform->getNumChildren() == 0) { if (childNode && childNode->node()) { - transform->addChild(childNode->node()); + updated |= transform->addChild(childNode->node()); } } else { if (childNode && childNode->node()) { if (transform->getChild(0) != childNode->node()) { - transform->removeChild(0, 1); - transform->addChild(childNode->node()); + updated |= transform->removeChild(0, 1); + updated |= transform->addChild(childNode->node()); } } else { - transform->removeChild(0, 1); + updated |= transform->removeChild(0, 1); } } + // if (updated) { + self->emitNodeChanged(); + // } + } - osgEarth::MapNode *mapNode = NULL; + void updateSceneNode() + { if (sceneNode && sceneNode->node()) { - mapNode = osgEarth::MapNode::findMapNode(sceneNode->node()); + osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneNode->node()); if (mapNode) { transform->setTerrain(mapNode->getTerrain()); } else { - qWarning() << "OSGGeoTransformNode::updateNode - scene data does not contain a map node"; + qWarning() << "OSGGeoTransformNode::updateScene - scene data does not contain a map node"; } } + } + + void updatePosition() + { + osgEarth::MapNode *mapNode = NULL; + + if (sceneNode && sceneNode->node()) { + mapNode = osgEarth::MapNode::findMapNode(sceneNode->node()); + } + if (!mapNode) { + qWarning() << "OSGGeoTransformNode::updatePosition - scene node does not contain a map node"; + } osgEarth::GeoPoint geoPoint; if (mapNode) { @@ -139,49 +172,24 @@ public: transform->setPosition(geoPoint); } - osgEarth::GeoTransform *getOrCreateTransform() - { - if (transform.valid()) { - return transform.get(); - } - - transform = new osgEarth::GeoTransform(); - transform->setAutoRecomputeHeights(true); - - self->setNode(transform); - - return transform.get(); - } - - OSGGeoTransformNode *const self; - - osg::ref_ptr transform; - - OSGNode *childNode; - OSGNode *sceneNode; - - float offset; - - bool clampToTerrain; - bool intoTerrain; - - QVector3D position; - private slots: - void onChildNodeChanged(osg::Node *node) { qDebug() << "OSGGeoTransformNode::onChildNodeChanged" << node; - self->setDirty(); + updateTransformNode(); } void onSceneNodeChanged(osg::Node *node) { qDebug() << "OSGGeoTransformNode::onSceneNodeChanged" << node; - self->setDirty(); + // TODO } }; +/* class OSGGeoTransformNode */ + +enum DirtyFlag { Child = 1 << 0, Scene = 1 << 1, Position = 1 << 2, Clamp = 1 << 3 }; + OSGGeoTransformNode::OSGGeoTransformNode(QObject *parent) : OSGNode(parent), h(new Hidden(this)) { qDebug() << "OSGGeoTransformNode::OSGGeoTransformNode"; @@ -189,31 +197,33 @@ OSGGeoTransformNode::OSGGeoTransformNode(QObject *parent) : OSGNode(parent), h(n OSGGeoTransformNode::~OSGGeoTransformNode() { - qDebug() << "OSGGeoTransformNode::~OSGGeoTransformNode"; + // qDebug() << "OSGGeoTransformNode::~OSGGeoTransformNode"; delete h; } -OSGNode *OSGGeoTransformNode::modelData() +OSGNode *OSGGeoTransformNode::childNode() { return h->childNode; } -void OSGGeoTransformNode::setModelData(OSGNode *node) +void OSGGeoTransformNode::setChildNode(OSGNode *node) { if (h->acceptChildNode(node)) { - emit modelDataChanged(node); + setDirty(Child); + emit childNodeChanged(node); } } -OSGNode *OSGGeoTransformNode::sceneData() +OSGNode *OSGGeoTransformNode::sceneNode() { return h->sceneNode; } -void OSGGeoTransformNode::setSceneData(OSGNode *node) +void OSGGeoTransformNode::setSceneNode(OSGNode *node) { if (h->acceptSceneNode(node)) { - emit sceneDataChanged(node); + setDirty(Scene); + emit sceneNodeChanged(node); } } @@ -226,7 +236,7 @@ void OSGGeoTransformNode::setClampToTerrain(bool arg) { if (h->clampToTerrain != arg) { h->clampToTerrain = arg; - setDirty(); + setDirty(Clamp); emit clampToTerrainChanged(clampToTerrain()); } } @@ -245,31 +255,36 @@ void OSGGeoTransformNode::setPosition(QVector3D arg) { if (h->position != arg) { h->position = arg; - setDirty(); + setDirty(Position); emit positionChanged(position()); } } void OSGGeoTransformNode::update() { - h->updateNode(); + if (isDirty(Child)) { + h->updateTransformNode(); + } + if (isDirty(Scene)) { + h->updateSceneNode(); + } + if (isDirty(Clamp)) {} + if (isDirty(Position)) { + h->updatePosition(); + } } void OSGGeoTransformNode::attach(osgViewer::View *view) { - // qDebug() << "OSGGeoTransformNode::attach " << view; - if (h->childNode) { - h->childNode->attach(view); - } + OSGNode::attach(h->childNode, view); + update(); + clearDirty(); } void OSGGeoTransformNode::detach(osgViewer::View *view) { - // qDebug() << "OSGGeoTransformNode::detach " << view; - if (h->childNode) { - h->childNode->detach(view); - } + OSGNode::detach(h->childNode, view); } } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.hpp index 6f9a5a6ea..9c2d81ccf 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.hpp @@ -38,9 +38,9 @@ namespace osgQtQuick { class OSGQTQUICK_EXPORT OSGGeoTransformNode : public OSGNode { Q_OBJECT // TODO rename to childNode - Q_PROPERTY(osgQtQuick::OSGNode *modelData READ modelData WRITE setModelData NOTIFY modelDataChanged) + Q_PROPERTY(osgQtQuick::OSGNode *modelData READ childNode WRITE setChildNode NOTIFY childNodeChanged) // TODO rename to sceneNode - Q_PROPERTY(osgQtQuick::OSGNode * sceneData READ sceneData WRITE setSceneData NOTIFY sceneDataChanged) + Q_PROPERTY(osgQtQuick::OSGNode * sceneData READ sceneNode WRITE setSceneNode NOTIFY sceneNodeChanged) Q_PROPERTY(bool clampToTerrain READ clampToTerrain WRITE setClampToTerrain NOTIFY clampToTerrainChanged) Q_PROPERTY(bool intoTerrain READ intoTerrain NOTIFY intoTerrainChanged) @@ -51,11 +51,11 @@ public: OSGGeoTransformNode(QObject *parent = 0); virtual ~OSGGeoTransformNode(); - OSGNode *modelData(); - void setModelData(OSGNode *node); + OSGNode *childNode(); + void setChildNode(OSGNode *node); - OSGNode *sceneData(); - void setSceneData(OSGNode *node); + OSGNode *sceneNode(); + void setSceneNode(OSGNode *node); bool clampToTerrain() const; void setClampToTerrain(bool arg); @@ -65,13 +65,10 @@ public: QVector3D position() const; void setPosition(QVector3D arg); - virtual void attach(osgViewer::View *view); - virtual void detach(osgViewer::View *view); - signals: - void modelDataChanged(OSGNode *node); + void childNodeChanged(OSGNode *node); - void sceneDataChanged(OSGNode *node); + void sceneNodeChanged(OSGNode *node); void clampToTerrainChanged(bool arg); void intoTerrainChanged(bool arg); @@ -83,6 +80,9 @@ private: Hidden *h; virtual void update(); + + virtual void attach(osgViewer::View *view); + virtual void detach(osgViewer::View *view); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGroup.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGroup.cpp index fb7cb8ea7..4918360d4 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGroup.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGroup.cpp @@ -33,118 +33,160 @@ #include namespace osgQtQuick { +enum DirtyFlag { Children = 1 << 0 }; + struct OSGGroup::Hidden : public QObject { Q_OBJECT -public: - Hidden(OSGGroup *node) : QObject(node), self(node), group(new osg::Group) - {} +private: + OSGGroup * self; - OSGGroup *self; - - osg::ref_ptr group; - - QList children; + osg::ref_ptr group; QMap cache; - static void append_child(QQmlListProperty *list, OSGNode *child) +public: + Hidden(OSGGroup *node) : QObject(node), self(node), group(new osg::Group) { - OSGGroup *group = qobject_cast(list->object); + group = new osg::Group(); + self->setNode(group); + } - if (group && child) { - group->h->cache[child] = child->node(); - group->h->children.append(child); - if (child->node()) { - group->h->group->addChild(child->node()); - emit group->nodeChanged(group->h->group); - } - QObject::connect(child, SIGNAL(nodeChanged(osg::Node *)), group->h, SLOT(onNodeChanged(osg::Node *))); + QList children; + + void appendChild(OSGNode *childNode) + { + cache[childNode] = childNode->node(); + children.append(childNode); + connect(childNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onChildNodeChanged(osg::Node *)), Qt::UniqueConnection); + self->setDirty(Children); + } + + int countChild() const + { + return children.size(); + } + + OSGNode *atChild(int index) const + { + if (index >= 0 && index < children.size()) { + return children[index]; } + return 0; + } + + void clearChild() + { + while (!children.isEmpty()) { + OSGNode *node = children.takeLast(); + disconnect(node); + } + children.clear(); + cache.clear(); + self->setDirty(Children); + } + + void updateGroupNode() + { + bool updated = false; + unsigned int index = 0; + + QListIterator i(children); + while (i.hasNext()) { + OSGNode *childNode = i.next(); + if (index < group->getNumChildren()) { + updated |= group->replaceChild(group->getChild(index), childNode->node()); + } else { + updated |= group->addChild(childNode->node()); + } + index++; + } + // removing eventual left overs + if (index < group->getNumChildren()) { + updated |= group->removeChild(index, group->getNumChildren() - index); + } + // if (updated) { + self->emitNodeChanged(); + // } + } + + /* QQmlListProperty */ + + static void append_child(QQmlListProperty *list, OSGNode *childNode) + { + Hidden *h = qobject_cast(list->object); + + h->appendChild(childNode); } static int count_child(QQmlListProperty *list) { - OSGGroup *group = qobject_cast(list->object); + Hidden *h = qobject_cast(list->object); - if (group) { - return group->h->children.size(); - } - - return 0; + return h->countChild(); } static OSGNode *at_child(QQmlListProperty *list, int index) { - OSGGroup *group = qobject_cast(list->object); + Hidden *h = qobject_cast(list->object); - if (group && index >= 0 && index < group->h->children.size()) { - return group->h->children[index]; - } - - return 0; + return h->atChild(index); } static void clear_child(QQmlListProperty *list) { - OSGGroup *group = qobject_cast(list->object); + Hidden *h = qobject_cast(list->object); - if (group) { - while (!group->h->children.isEmpty()) { - OSGNode *node = group->h->children.takeLast(); - if (node->parent() == group) { - node->deleteLater(); - } - if (!node->parent()) { - node->deleteLater(); - } - } - group->h->group->removeChild(0, group->h->group->getNumChildren()); - group->h->cache.clear(); - } + h->clearChild(); } -public slots: - void onNodeChanged(osg::Node *node) +private slots: + void onChildNodeChanged(osg::Node *node) { - qDebug() << "OSGGroup::nodeChanged" << node; + qDebug() << "OSGGroup::onChildNodeChanged" << node; OSGNode *obj = qobject_cast(sender()); if (obj) { osg::Node *cacheNode = cache.value(obj, NULL); if (cacheNode) { - group->removeChild(cacheNode); - } - if (node) { - group->addChild(node); + group->replaceChild(cacheNode, node); + } else { + // should not happen... } cache[obj] = node; - emit self->nodeChanged(group.get()); + // emit self->nodeChanged(group.get()); } } }; -OSGGroup::OSGGroup(QObject *parent) : - OSGNode(parent), h(new Hidden(this)) +/* class OSGGGroupNode */ + +OSGGroup::OSGGroup(QObject *parent) : OSGNode(parent), h(new Hidden(this)) { qDebug() << "OSGGroup::OSGGroup"; - setNode(h->group.get()); } OSGGroup::~OSGGroup() { - qDebug() << "OSGGroup::~OSGGroup"; + // qDebug() << "OSGGroup::~OSGGroup"; delete h; } QQmlListProperty OSGGroup::children() { - return QQmlListProperty(this, 0, + return QQmlListProperty(h, 0, &Hidden::append_child, &Hidden::count_child, &Hidden::at_child, &Hidden::clear_child); } +void OSGGroup::update() +{ + if (isDirty(Children)) { + h->updateGroupNode(); + } +} + void OSGGroup::attach(osgViewer::View *view) { // qDebug() << "OSGGroup::attach " << view; @@ -152,8 +194,10 @@ void OSGGroup::attach(osgViewer::View *view) while (i.hasNext()) { OSGNode *node = i.next(); // qDebug() << "OSGGroup::attach - child" << node; - node->attach(view); + OSGNode::attach(node, view); } + update(); + clearDirty(); } void OSGGroup::detach(osgViewer::View *view) @@ -163,7 +207,7 @@ void OSGGroup::detach(osgViewer::View *view) while (i.hasNext()) { OSGNode *node = i.next(); // qDebug() << "OSGGroup::detach - child" << node; - node->detach(view); + OSGNode::detach(node, view); } } } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGroup.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGroup.hpp index d9c07699f..c9a95a516 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGroup.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGGroup.hpp @@ -45,12 +45,14 @@ public: QQmlListProperty children(); - virtual void attach(osgViewer::View *view); - virtual void detach(osgViewer::View *view); - private: struct Hidden; Hidden *h; + + virtual void update(); + + virtual void attach(osgViewer::View *view); + virtual void detach(osgViewer::View *view); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.cpp index 01c99d82f..bd88005ae 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.cpp @@ -46,21 +46,21 @@ private: OSGNode::Hidden *const h; }; - -struct OSGNode::Hidden /*: public QObject*/ { - // Q_OBJECT +struct OSGNode::Hidden : public QObject { + Q_OBJECT friend class OSGNode; + public: - Hidden(OSGNode *node) : /*QObject(node),*/ self(node), dirty(0) + Hidden(OSGNode *node) : QObject(node), self(node), dirty(0) {} - bool isDirty(int flag) + bool isDirty(int mask) { - return (dirty && (1 << flag)) != 0; + return (dirty && mask) != 0; } - void setDirty(int flag) + void setDirty(int mask) { // qDebug() << "OSGNode::setDirty BEGIN"; if (!dirty) { @@ -74,7 +74,7 @@ public: node->setUpdateCallback(nodeUpdateCallback); } } - dirty |= 1 << flag; + dirty |= mask; // qDebug() << "OSGNode::setDirty DONE"; } @@ -161,27 +161,48 @@ void OSGNode::setNode(osg::Node *node) bool OSGNode::isDirty() { - return h->isDirty(1); + return h->isDirty(0xFFFFFFFF); } -bool OSGNode::isDirty(int flag) +bool OSGNode::isDirty(int mask) { - return h->isDirty(flag); + return h->isDirty(mask); } -void OSGNode::setDirty() +void OSGNode::setDirty(int mask) { - h->setDirty(1); + h->setDirty(mask); } -void OSGNode::setDirty(int flag) +void OSGNode::clearDirty() { - h->setDirty(flag); + h->clearDirty(); } +void OSGNode::attach(OSGNode *node, osgViewer::View *view) +{ + if (!node) { + return; + } + node->attach(view); +} + +void OSGNode::detach(OSGNode *node, osgViewer::View *view) +{ + if (!node) { + return; + } + node->detach(view); +} + +void OSGNode::update() +{} + void OSGNode::attach(osgViewer::View *view) {} void OSGNode::detach(osgViewer::View *view) {} } // namespace osgQtQuick + +#include "OSGNode.moc" diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.hpp index bdfba4932..e4690afb8 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGNode.hpp @@ -56,6 +56,7 @@ namespace osgQtQuick { class OSGQTQUICK_EXPORT OSGNode : public QObject { Q_OBJECT + friend class OSGViewport; friend class NodeUpdateCallback; public: @@ -65,14 +66,19 @@ public: osg::Node *node() const; void setNode(osg::Node *node); - 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); + bool isDirty(int mask); + void setDirty(int mask); + void clearDirty(); + + void emitNodeChanged() + { + emit nodeChanged(node()); + } + + void attach(OSGNode *node, osgViewer::View *view); + void detach(OSGNode *node, osgViewer::View *view); signals: void nodeChanged(osg::Node *node) const; @@ -81,7 +87,10 @@ private: struct Hidden; Hidden *h; - virtual void update() {}; + virtual void attach(osgViewer::View *view); + virtual void detach(osgViewer::View *view); + + 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 a5b6246c7..cffd64255 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGShapeNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGShapeNode.cpp @@ -40,13 +40,17 @@ namespace osgQtQuick { struct OSGShapeNode::Hidden : public QObject { Q_OBJECT +private: + OSGShapeNode * self; + public: - Hidden(OSGShapeNode *node) : QObject(node), self(node), shapeType(ShapeType::Sphere) {} + ShapeType::Enum shapeType; - void realize() + Hidden(OSGShapeNode *node) : QObject(node), self(node), shapeType(ShapeType::Sphere) + {} + + void updateNode() { - qDebug() << "OSGShapeNode::realize"; - osg::Node *node = NULL; switch (shapeType) { @@ -63,40 +67,26 @@ public: node = ShapeUtils::create3DAxis(); break; } - - // Add the node to the scene: + // Add the node to the scene self->setNode(node); } - - bool acceptShapeType(ShapeType::Enum type) - { - if (shapeType == type) { - return false; - } - qDebug() << "OSGShapeNode::acceptShapeType" << type; - - shapeType = type; - realize(); - - return true; - } - - OSGShapeNode *self; - - ShapeType::Enum shapeType; }; +/* class OSGShapeNode */ + +enum DirtyFlag { Type = 1 << 0 }; + // TODO turn into generic shape node... // see http://trac.openscenegraph.org/projects/osg//wiki/Support/Tutorials/TransformsAndStates OSGShapeNode::OSGShapeNode(QObject *parent) : OSGNode(parent), h(new Hidden(this)) { qDebug() << "OSGShapeNode::OSGShapeNode"; - h->realize(); + setShapeType(ShapeType::Sphere); } OSGShapeNode::~OSGShapeNode() { - qDebug() << "OSGShapeNode::~OSGShapeNode"; + // qDebug() << "OSGShapeNode::~OSGShapeNode"; delete h; } @@ -107,10 +97,28 @@ ShapeType::Enum OSGShapeNode::shapeType() const void OSGShapeNode::setShapeType(ShapeType::Enum type) { - if (h->acceptShapeType(type)) { - emit shapeTypeChanged(shapeType()); + if (h->shapeType != type) { + h->shapeType = type; + setDirty(Type); + emit shapeTypeChanged(type); } } + +void OSGShapeNode::update() +{ + if (isDirty(Type)) { + h->updateNode(); + } +} + +void OSGShapeNode::attach(osgViewer::View *view) +{ + update(); + clearDirty(); +} + +void OSGShapeNode::detach(osgViewer::View *view) +{} } // namespace osgQtQuick #include "OSGShapeNode.moc" diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGShapeNode.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGShapeNode.hpp index 81e5d5bce..409779d4f 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGShapeNode.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGShapeNode.hpp @@ -55,6 +55,11 @@ signals: private: struct Hidden; Hidden *h; + + virtual void update(); + + virtual void attach(osgViewer::View *view); + virtual void detach(osgViewer::View *view); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGSkyNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGSkyNode.cpp index 208c9f71f..f23f69770 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGSkyNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGSkyNode.cpp @@ -42,8 +42,19 @@ namespace osgQtQuick { struct OSGSkyNode::Hidden : public QObject { Q_OBJECT +private: + OSGSkyNode * const self; + + osg::ref_ptr skyNode; + public: - Hidden(OSGSkyNode *node) : QObject(node), self(node), sceneData(NULL), sunLightEnabled(true), minimumAmbientLight(0.03) + OSGNode *sceneNode; + + bool sunLightEnabled; + QDateTime dateTime; + double minimumAmbientLight; + + Hidden(OSGSkyNode *node) : QObject(node), self(node), sceneNode(NULL), sunLightEnabled(true), minimumAmbientLight(0.03) { dateTime = QDateTime::currentDateTime(); } @@ -54,59 +65,60 @@ public: bool acceptSceneNode(OSGNode *node) { qDebug() << "OSGSkyNode::acceptSceneNode" << node; - if (sceneData == node) { + if (sceneNode == node) { return false; } - if (sceneData) { - disconnect(sceneData); + if (sceneNode) { + disconnect(sceneNode); } - sceneData = node; + sceneNode = node; - if (sceneData) { - acceptNode(sceneData->node()); - connect(sceneData, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onNodeChanged(osg::Node *))); + if (sceneNode) { + connect(sceneNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onSceneNodeChanged(osg::Node *))); } return true; } - bool acceptNode(osg::Node *node) + void updateSkyNode() { - qDebug() << "OSGSkyNode::acceptNode" << node; - - osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(node); + if (!sceneNode || !sceneNode->node()) { + qWarning() << "OSGSkyNode::acceptNode - scene node not valid"; + self->setNode(NULL); + return; + } + osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneNode->node()); if (!mapNode) { - qWarning() << "OSGSkyNode::acceptNode - scene data does not contain a map node"; - return false; + qWarning() << "OSGSkyNode::acceptNode - scene node does not contain a map node"; + self->setNode(NULL); + return; } if (!mapNode->getMap()->isGeocentric()) { qWarning() << "OSGSkyNode::acceptNode - map node is not geocentric"; - return false; + self->setNode(NULL); + return; } // create sky node - skyNode = createSimpleSky(mapNode); - // skyNode = createSilverLiningSky(mapNode); + if (!skyNode.valid()) { + skyNode = createSimpleSky(mapNode); + // skyNode = createSilverLiningSky(mapNode); - acceptSunLightEnabled(sunLightEnabled); - acceptDateTime(dateTime); - acceptMinimumAmbientLight(minimumAmbientLight); + // Ocean + // const osgEarth::Config & externals = mapNode->externalConfig(); + // if (externals.hasChild("ocean")) { + // s_ocean = osgEarth::Util::OceanNode::create(osgEarth::Util::OceanOptions(externals.child("ocean")), mapNode); + // if (s_ocean) root->addChild(s_ocean); - // skyNode->setStarsVisible(false); - - // Ocean - // const osgEarth::Config & externals = mapNode->externalConfig(); - // if (externals.hasChild("ocean")) { - // s_ocean = osgEarth::Util::OceanNode::create(osgEarth::Util::OceanOptions(externals.child("ocean")), mapNode); - // if (s_ocean) root->addChild(s_ocean); - - skyNode->addChild(node); - - self->setNode(skyNode); - - return true; + skyNode->addChild(sceneNode->node()); + self->setNode(skyNode); + } else { + skyNode->removeChild(0, 1); + skyNode->addChild(sceneNode->node()); + self->emitNodeChanged(); + } } osgEarth::Util::SkyNode *createSimpleSky(osgEarth::MapNode *mapNode) @@ -130,65 +142,46 @@ public: } */ - bool acceptSunLightEnabled(bool enabled) + void updateSunLightEnabled() { - // qDebug() << "OSGSkyNode::acceptSunLightEnabled" << enabled; - - this->sunLightEnabled = enabled; - - // TODO should be done in a node visitor... - if (skyNode) { - // skyNode->setLighting(sunLightEnabled ? osg::StateAttribute::ON : osg::StateAttribute::OFF); + if (!skyNode.valid()) { + return; } - - return true; + // skyNode->setLighting(sunLightEnabled ? osg::StateAttribute::ON : osg::StateAttribute::OFF); } - bool acceptDateTime(QDateTime dateTime) + void updateDateTime() { - qDebug() << "OSGSkyNode::acceptDateTime" << dateTime; - + if (!skyNode.valid()) { + return; + } if (!dateTime.isValid()) { qWarning() << "OSGSkyNode::acceptDateTime - invalid date/time" << dateTime; - return false; } - this->dateTime = dateTime; - - // TODO should be done in a node visitor... - if (skyNode) { - QDate date = dateTime.date(); - QTime time = dateTime.time(); - double hours = time.hour() + (double)time.minute() / 60.0 + (double)time.second() / 3600.0; - skyNode->setDateTime(osgEarth::DateTime(date.year(), date.month(), date.day(), hours)); - } - - return true; + QDate date = dateTime.date(); + QTime time = dateTime.time(); + double hours = time.hour() + (double)time.minute() / 60.0 + (double)time.second() / 3600.0; + skyNode->setDateTime(osgEarth::DateTime(date.year(), date.month(), date.day(), hours)); } - bool acceptMinimumAmbientLight(double minimumAmbientLight) + void updateMinimumAmbientLight() { - // qDebug() << "OSGSkyNode::acceptMinimumAmbientLight" << minimumAmbientLight; - - this->minimumAmbientLight = minimumAmbientLight; - - // TODO should be done in a node visitor... - if (skyNode) { - double d = minimumAmbientLight; - // skyNode->getSunLight()->setAmbient(osg::Vec4(d, d, d, 1.0f)); - skyNode->setMinimumAmbient(osg::Vec4(d, d, d, 1.0f)); + if (!skyNode.valid()) { + return; } - - return true; + double d = minimumAmbientLight; + // skyNode->getSunLight()->setAmbient(osg::Vec4(d, d, d, 1.0f)); + skyNode->setMinimumAmbient(osg::Vec4(d, d, d, 1.0f)); } void attachSkyNode(osgViewer::View *view) { if (!skyNode.valid()) { - qWarning() << "OSGSkyNode::attach - invalid sky node" << skyNode; + qWarning() << "OSGSkyNode::attachSkyNode - invalid sky node" << skyNode; return; } - skyNode->attach(view, 0); + skyNode->attach(view); } void detachSkyNode(osgViewer::View *view) @@ -196,44 +189,41 @@ public: // TODO find a way to detach the skyNode (?) } - OSGSkyNode *const self; - - OSGNode *sceneData; - osg::ref_ptr skyNode; - - bool sunLightEnabled; - QDateTime dateTime; - double minimumAmbientLight; - private slots: - - void onNodeChanged(osg::Node *node) + void onSceneNodeChanged(osg::Node *node) { - qDebug() << "OSGSkyNode::onNodeChanged" << node; - acceptNode(node); + qDebug() << "OSGSkyNode::onSceneNodeChanged" << node; + updateSkyNode(); } }; +/* class OSGSkyNode */ + +enum DirtyFlag { Child = 1 << 0, DateTime = 1 << 1, Light = 1 << 2 }; + OSGSkyNode::OSGSkyNode(QObject *parent) : OSGNode(parent), h(new Hidden(this)) { qDebug() << "OSGSkyNode::OSGSkyNode"; + setSunLightEnabled(true); + setMinimumAmbientLight(0.03); } OSGSkyNode::~OSGSkyNode() { - qDebug() << "OSGSkyNode::~OSGSkyNode"; + // qDebug() << "OSGSkyNode::~OSGSkyNode"; delete h; } -OSGNode *OSGSkyNode::sceneData() +OSGNode *OSGSkyNode::sceneNode() { - return h->sceneData; + return h->sceneNode; } -void OSGSkyNode::setSceneData(OSGNode *node) +void OSGSkyNode::setSceneNode(OSGNode *node) { if (h->acceptSceneNode(node)) { - emit sceneDataChanged(node); + setDirty(Child); + emit sceneNodeChanged(node); } } @@ -242,10 +232,12 @@ bool OSGSkyNode::sunLightEnabled() return h->sunLightEnabled; } -void OSGSkyNode::setSunLightEnabled(bool arg) +void OSGSkyNode::setSunLightEnabled(bool enabled) { - if (h->acceptSunLightEnabled(arg)) { - emit sunLightEnabledChanged(sunLightEnabled()); + if (h->sunLightEnabled != enabled) { + h->sunLightEnabled = enabled; + setDirty(Light); + emit sunLightEnabledChanged(enabled); } } @@ -254,10 +246,12 @@ QDateTime OSGSkyNode::dateTime() return h->dateTime; } -void OSGSkyNode::setDateTime(QDateTime arg) +void OSGSkyNode::setDateTime(QDateTime dateTime) { - if (h->acceptDateTime(arg)) { - emit dateTimeChanged(dateTime()); + if (h->dateTime != dateTime) { + h->dateTime = dateTime; + setDirty(DateTime); + emit dateTimeChanged(dateTime); } } @@ -266,29 +260,44 @@ double OSGSkyNode::minimumAmbientLight() return h->minimumAmbientLight; } -void OSGSkyNode::setMinimumAmbientLight(double arg) +void OSGSkyNode::setMinimumAmbientLight(double ambient) { - if (h->acceptMinimumAmbientLight(arg)) { - emit minimumAmbientLightChanged(minimumAmbientLight()); + if (h->minimumAmbientLight != ambient) { + h->minimumAmbientLight = ambient; + setDirty(Light); + emit minimumAmbientLightChanged(ambient); + } +} + +void OSGSkyNode::update() +{ + if (isDirty(Child)) { + h->updateSkyNode(); + } + if (isDirty(Light)) { + h->updateSunLightEnabled(); + h->updateMinimumAmbientLight(); + } + if (isDirty(DateTime)) { + h->updateDateTime(); } } void OSGSkyNode::attach(osgViewer::View *view) { // qDebug() << "OSGSkyNode::attach " << view; - if (h->sceneData) { - h->sceneData->attach(view); - } + OSGNode::attach(h->sceneNode, view); + h->attachSkyNode(view); + update(); + clearDirty(); } void OSGSkyNode::detach(osgViewer::View *view) { // qDebug() << "OSGSkyNode::detach " << view; h->detachSkyNode(view); - if (h->sceneData) { - h->sceneData->detach(view); - } + OSGNode::detach(h->sceneNode, view); } } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGSkyNode.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGSkyNode.hpp index d84f17ece..b3332916f 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGSkyNode.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGSkyNode.hpp @@ -44,7 +44,8 @@ QT_END_NAMESPACE namespace osgQtQuick { class OSGQTQUICK_EXPORT OSGSkyNode : public OSGNode { - Q_OBJECT Q_PROPERTY(osgQtQuick::OSGNode *sceneData READ sceneData WRITE setSceneData NOTIFY sceneDataChanged) + // TODO rename to sceneNode + Q_OBJECT Q_PROPERTY(osgQtQuick::OSGNode *sceneData READ sceneNode WRITE setSceneNode NOTIFY sceneNodeChanged) Q_PROPERTY(bool sunLightEnabled READ sunLightEnabled WRITE setSunLightEnabled NOTIFY sunLightEnabledChanged) Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY dateTimeChanged) @@ -54,8 +55,8 @@ public: OSGSkyNode(QObject *parent = 0); virtual ~OSGSkyNode(); - OSGNode *sceneData(); - void setSceneData(OSGNode *node); + OSGNode *sceneNode(); + void setSceneNode(OSGNode *node); bool sunLightEnabled(); void setSunLightEnabled(bool arg); @@ -66,11 +67,8 @@ public: double minimumAmbientLight(); void setMinimumAmbientLight(double arg); - virtual void attach(osgViewer::View *view); - virtual void detach(osgViewer::View *view); - signals: - void sceneDataChanged(OSGNode *node); + void sceneNodeChanged(OSGNode *node); void sunLightEnabledChanged(bool arg); void dateTimeChanged(QDateTime arg); @@ -79,6 +77,11 @@ signals: private: struct Hidden; Hidden *h; + + virtual void update(); + + virtual void attach(osgViewer::View *view); + virtual void detach(osgViewer::View *view); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTextNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTextNode.cpp index f7016b3c0..43fcaefd1 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTextNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTextNode.cpp @@ -37,34 +37,61 @@ #include namespace osgQtQuick { -struct OSGTextNode::Hidden { -public: +struct OSGTextNode::Hidden : public QObject { + Q_OBJECT + +private: + OSGTextNode * const self; + osg::ref_ptr text; + +public: + QString textString; + QColor color; + + Hidden(OSGTextNode *node) : QObject(node), self(node) + { + osg::ref_ptr textFont = createFont(QFont("Times")); + + text = createText(osg::Vec3(-100, 20, 0), "Hello World", 20.0f, + textFont.get()); + osg::ref_ptr textGeode = new osg::Geode(); + textGeode->addDrawable(text.get()); + #if 0 + text->setAutoRotateToScreen(true); + self->setNode(textGeode.get()); + #else + osg::Camera *camera = createHUDCamera(-100, 100, -100, 100); + camera->addChild(textGeode.get()); + camera->getOrCreateStateSet()->setMode( + GL_LIGHTING, osg::StateAttribute::OFF); + self->setNode(camera); + #endif + } + + void updateText() + { + text->setText(textString.toStdString(), osgText::String::ENCODING_UTF8); + } + + void updateColor() + { + osg::Vec4 osgColor( + color.redF(), + color.greenF(), + color.blueF(), + color.alphaF()); + + text->setColor(osgColor); + } }; -OSGTextNode::OSGTextNode(QObject *node) : OSGNode(node), h(new Hidden) -{ - osg::ref_ptr textFont = createFont(QFont("Times")); +/* class OSGTextNode */ - h->text = createText(osg::Vec3(-100, 20, 0), - "The osgQtQuick :-)\n" - "И даже по русски!", - 20.0f, - textFont.get()); - osg::ref_ptr textGeode = new osg::Geode(); - h->text->setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); - textGeode->addDrawable(h->text.get()); -#if 0 - h->text->setAutoRotateToScreen(true); - setNode(textGeode.get()); -#else - osg::Camera *camera = createHUDCamera(-100, 100, -100, 100); - camera->addChild(textGeode.get()); - camera->getOrCreateStateSet()->setMode( - GL_LIGHTING, osg::StateAttribute::OFF); - setNode(camera); -#endif -} +enum DirtyFlag { Text = 1 << 0, Color = 1 << 1 }; + +OSGTextNode::OSGTextNode(QObject *node) : OSGNode(node), h(new Hidden(this)) +{} OSGTextNode::~OSGTextNode() { @@ -73,42 +100,50 @@ OSGTextNode::~OSGTextNode() QString OSGTextNode::text() const { - return QString::fromUtf8( - h->text->getText().createUTF8EncodedString().data()); + return h->textString; } void OSGTextNode::setText(const QString &text) { - std::string oldText = h->text->getText().createUTF8EncodedString(); - - if (text.toStdString() != oldText) { - h->text->setText(text.toStdString(), osgText::String::ENCODING_UTF8); + if (h->textString != text) { + h->textString != text; + setDirty(Text); emit textChanged(text); } } QColor OSGTextNode::color() const { - const osg::Vec4 osgColor = h->text->getColor(); - - return QColor::fromRgbF( - osgColor.r(), - osgColor.g(), - osgColor.b(), - osgColor.a()); + return h->color; } void OSGTextNode::setColor(const QColor &color) { - osg::Vec4 osgColor( - color.redF(), - color.greenF(), - color.blueF(), - color.alphaF()); - - if (h->text->getColor() != osgColor) { - h->text->setColor(osgColor); + if (h->color != color) { + h->color != color; + setDirty(Color); emit colorChanged(color); } } + +void OSGTextNode::update() +{ + if (isDirty(Text)) { + h->updateText(); + } + if (isDirty(Color)) { + h->updateColor(); + } +} + +void OSGTextNode::attach(osgViewer::View *view) +{ + update(); + clearDirty(); +} + +void OSGTextNode::detach(osgViewer::View *view) +{} } // namespace osgQtQuick + +#include "OSGTextNode.moc" diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTextNode.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTextNode.hpp index 5a0939478..aa3deb770 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTextNode.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTextNode.hpp @@ -52,11 +52,14 @@ signals: void textChanged(const QString &text); void colorChanged(const QColor &color); -public slots: - private: struct Hidden; Hidden *h; + + virtual void update(); + + virtual void attach(osgViewer::View *view); + virtual void detach(osgViewer::View *view); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.cpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.cpp index 16ebe1c31..816b3f3d5 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.cpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.cpp @@ -37,10 +37,23 @@ namespace osgQtQuick { struct OSGTransformNode::Hidden : public QObject { Q_OBJECT +private: + OSGTransformNode * const self; + + osg::ref_ptr transform; + public: + OSGNode *childNode; + + QVector3D scale; + QVector3D attitude; + QVector3D position; Hidden(OSGTransformNode *node) : QObject(node), self(node), childNode(NULL) - {} + { + transform = new osg::PositionAttitudeTransform(); + self->setNode(transform); + } bool acceptChildNode(OSGNode *node) { @@ -62,35 +75,40 @@ public: return true; } - void updateNode() + void updateTransformNode() { - // qDebug() << "OSGTransformNode::updateNode" << this; - - osg::PositionAttitudeTransform *transform = getOrCreateTransform(); + bool updated = false; if (transform->getNumChildren() == 0) { if (childNode && childNode->node()) { - transform->addChild(childNode->node()); + updated |= transform->addChild(childNode->node()); } } else { if (childNode && childNode->node()) { if (transform->getChild(0) != childNode->node()) { - transform->removeChild(0, 1); - transform->addChild(childNode->node()); + updated |= transform->removeChild(0, 1); + updated |= transform->addChild(childNode->node()); } } else { - transform->removeChild(0, 1); + updated |= transform->removeChild(0, 1); } } + // if (updated) { + self->emitNodeChanged(); + // } + } - // scale + void updateScale() + { 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); transform->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON); } + } - // attitude + void updateAttitude() + { double roll = osg::DegreesToRadians(attitude.x()); double pitch = osg::DegreesToRadians(attitude.y()); double yaw = osg::DegreesToRadians(attitude.z()); @@ -98,45 +116,30 @@ public: roll, osg::Vec3d(0, 1, 0), pitch, osg::Vec3d(1, 0, 0), yaw, osg::Vec3d(0, 0, -1)); + transform->setAttitude(q); // position transform->setPosition(osg::Vec3d(position.x(), position.y(), position.z())); } - osg::PositionAttitudeTransform *getOrCreateTransform() + void updatePosition() { - if (transform.valid()) { - return transform.get(); - } - - transform = new osg::PositionAttitudeTransform(); - - - self->setNode(transform); - - return transform.get(); + transform->setPosition(osg::Vec3d(position.x(), position.y(), position.z())); } - OSGTransformNode *const self; - - osg::ref_ptr transform; - - OSGNode *childNode; - - QVector3D scale; - QVector3D attitude; - QVector3D position; - private slots: - void onChildNodeChanged(osg::Node *node) { qDebug() << "OSGTransformNode::onChildNodeChanged" << node; - self->setDirty(); + updateTransformNode(); } }; +/* class OSGTransformNode */ + +enum DirtyFlag { Child = 1 << 0, Scale = 1 << 1, Position = 1 << 2, Attitude = 1 << 3 }; + OSGTransformNode::OSGTransformNode(QObject *parent) : OSGNode(parent), h(new Hidden(this)) { qDebug() << "OSGTransformNode::OSGTransformNode"; @@ -144,19 +147,20 @@ OSGTransformNode::OSGTransformNode(QObject *parent) : OSGNode(parent), h(new Hid OSGTransformNode::~OSGTransformNode() { - qDebug() << "OSGTransformNode::~OSGTransformNode"; + // qDebug() << "OSGTransformNode::~OSGTransformNode"; delete h; } -OSGNode *OSGTransformNode::modelData() +OSGNode *OSGTransformNode::childNode() { return h->childNode; } -void OSGTransformNode::setModelData(OSGNode *node) +void OSGTransformNode::setChildNode(OSGNode *node) { if (h->acceptChildNode(node)) { - emit modelDataChanged(node); + setDirty(Child); + emit childNodeChanged(node); } } @@ -169,7 +173,7 @@ void OSGTransformNode::setScale(QVector3D arg) { if (h->scale != arg) { h->scale = arg; - setDirty(); + setDirty(Scale); emit scaleChanged(scale()); } } @@ -183,7 +187,7 @@ void OSGTransformNode::setAttitude(QVector3D arg) { if (h->attitude != arg) { h->attitude = arg; - setDirty(); + setDirty(Attitude); emit attitudeChanged(attitude()); } } @@ -197,31 +201,38 @@ void OSGTransformNode::setPosition(QVector3D arg) { if (h->position != arg) { h->position = arg; - setDirty(); + setDirty(Position); emit positionChanged(position()); } } void OSGTransformNode::update() { - h->updateNode(); + if (isDirty(Child)) { + h->updateTransformNode(); + } + if (isDirty(Scale)) { + h->updateScale(); + } + if (isDirty(Attitude)) { + h->updateAttitude(); + } + if (isDirty(Position)) { + h->updatePosition(); + } } void OSGTransformNode::attach(osgViewer::View *view) { - // qDebug() << "OSGTransformNode::attach " << view; - if (h->childNode) { - h->childNode->attach(view); - } + OSGNode::attach(h->childNode, view); + update(); + clearDirty(); } void OSGTransformNode::detach(osgViewer::View *view) { - // qDebug() << "OSGTransformNode::detach " << view; - if (h->childNode) { - h->childNode->detach(view); - } + OSGNode::detach(h->childNode, view); } } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.hpp index aff685f2f..fb42dd0a8 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGTransformNode.hpp @@ -38,7 +38,7 @@ namespace osgQtQuick { class OSGQTQUICK_EXPORT OSGTransformNode : public OSGNode { Q_OBJECT // TODO rename to childNode - Q_PROPERTY(osgQtQuick::OSGNode *modelData READ modelData WRITE setModelData NOTIFY modelDataChanged) + Q_PROPERTY(osgQtQuick::OSGNode *modelData READ childNode WRITE setChildNode NOTIFY childNodeChanged) Q_PROPERTY(QVector3D scale READ scale WRITE setScale NOTIFY scaleChanged) Q_PROPERTY(QVector3D attitude READ attitude WRITE setAttitude NOTIFY attitudeChanged) @@ -48,8 +48,8 @@ public: OSGTransformNode(QObject *parent = 0); virtual ~OSGTransformNode(); - OSGNode *modelData(); - void setModelData(OSGNode *node); + OSGNode *childNode(); + void setChildNode(OSGNode *node); QVector3D scale() const; void setScale(QVector3D arg); @@ -60,11 +60,8 @@ public: QVector3D position() const; void setPosition(QVector3D arg); - virtual void attach(osgViewer::View *view); - virtual void detach(osgViewer::View *view); - signals: - void modelDataChanged(OSGNode *node); + void childNodeChanged(OSGNode *node); void scaleChanged(QVector3D arg); void attitudeChanged(QVector3D arg); @@ -75,6 +72,9 @@ private: Hidden *h; virtual void update(); + + virtual void attach(osgViewer::View *view); + virtual void detach(osgViewer::View *view); }; } // namespace osgQtQuick diff --git a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.hpp b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.hpp index 56cf6bdf0..4b32398b4 100644 --- a/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.hpp +++ b/ground/gcs/src/libs/osgearth/osgQtQuick/OSGViewport.hpp @@ -72,11 +72,8 @@ public: OSGCamera *camera(); void setCamera(OSGCamera *camera); - virtual Renderer *createRenderer() const; - virtual void releaseResources(); - - virtual void attach(osgViewer::View *view); - virtual void detach(osgViewer::View *view); + Renderer *createRenderer() const; + void releaseResources(); signals: void updateModeChanged(UpdateMode::Enum mode); @@ -97,6 +94,9 @@ protected: QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData); + void attach(osgViewer::View *view); + void detach(osgViewer::View *view); + private: struct Hidden; Hidden *h;