1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-12-01 09:24:10 +01:00

LP-29 factorize update callback handling up into OSGNode

allows "on demand" mode to work which can drastically reduce cpu usage in some cases
This commit is contained in:
Philippe Renon 2016-03-08 03:29:00 +01:00
parent a4fb576d4b
commit 223d8f30e0
19 changed files with 291 additions and 261 deletions

View File

@ -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

View File

@ -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<osg::Camera> 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<osg::Camera> camera;
osg::ref_ptr<CameraUpdateCallback> 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());

View File

@ -29,6 +29,7 @@
#define _H_OSGQTQUICK_OSGCAMERA_H_
#include "Export.hpp"
#include "OSGNode.hpp"
#include <QObject>
#include <QVector3D>
@ -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

View File

@ -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

View File

@ -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<osgEarth::GeoTransform> 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)

View File

@ -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

View File

@ -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<OSGNode> OSGGroup::children()

View File

@ -28,15 +28,118 @@
#include "OSGNode.hpp"
#include <osg/Node>
#include <osg/NodeVisitor>
#include <QListIterator>
#include <qDebug>
namespace osgQtQuick {
struct OSGNode::Hidden {
osg::ref_ptr<osg::Node> 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<osg::Node> node;
osg::ref_ptr<osg::NodeCallback> 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)
{}

View File

@ -32,6 +32,18 @@
#include <QObject>
/**
* 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

View File

@ -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

View File

@ -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()

View File

@ -42,9 +42,7 @@ public:
osg::ref_ptr<osgText::Text> text;
};
OSGTextNode::OSGTextNode(QObject *parent) :
osgQtQuick::OSGNode(parent),
h(new Hidden)
OSGTextNode::OSGTextNode(QObject *node) : OSGNode(node), h(new Hidden)
{
osg::ref_ptr<osgText::Font> textFont = createFont(QFont("Times"));

View File

@ -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<osg::PositionAttitudeTransform> 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)

View File

@ -73,6 +73,8 @@ signals:
private:
struct Hidden;
Hidden *h;
virtual void update();
};
} // namespace osgQtQuick

View File

@ -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

View File

@ -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;
}

View File

@ -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
}

View File

@ -60,7 +60,7 @@ Item {
OSGCamera {
id: camera
fieldOfView: 90
node: transformNode
sceneNode: transformNode
}
}

View File

@ -57,7 +57,7 @@ OSGViewport {
OSGCamera {
id: camera
fieldOfView: 100
sceneData: terrainNode
sceneNode: terrainNode
logarithmicDepthBuffer: true
clampToTerrain: true
manipulatorMode: ManipulatorMode.User