mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-20 10:54:14 +01:00
LP-29 factorize dirty flag handling in new DirtySupport class
simplifies OSGNode and OSGCameraManipulator OSGViewport should use DirtySupport too
This commit is contained in:
parent
c1d0d03ba0
commit
a124ddd5da
145
ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.cpp
Normal file
145
ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.cpp
Normal file
@ -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 <osg/Node>
|
||||
#include <osg/NodeVisitor>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
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<osg::NodeCallback> 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
|
63
ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.hpp
Normal file
63
ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.hpp
Normal file
@ -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_
|
@ -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) {
|
||||
|
@ -144,7 +144,7 @@ public:
|
||||
|
||||
void updatePosition()
|
||||
{
|
||||
qDebug() << "OSGGeoTransformNode::updatePosition" << position;
|
||||
// qDebug() << "OSGGeoTransformNode::updatePosition" << position;
|
||||
|
||||
osgEarth::MapNode *mapNode = NULL;
|
||||
if (sceneNode && sceneNode->node()) {
|
||||
|
@ -27,27 +27,16 @@
|
||||
|
||||
#include "OSGNode.hpp"
|
||||
|
||||
#include "DirtySupport.hpp"
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/NodeVisitor>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
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<osg::Node> node;
|
||||
|
||||
osg::ref_ptr<osg::NodeCallback> 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);
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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<osg::GraphicsContext> 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<QSGSimpleTextureNode *>(node);
|
||||
return node;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "OSGCameraManipulator.hpp"
|
||||
|
||||
#include "../DirtySupport.hpp"
|
||||
#include "../OSGNode.hpp"
|
||||
|
||||
#include <osgGA/CameraManipulator>
|
||||
@ -34,11 +35,13 @@
|
||||
#include <QDebug>
|
||||
|
||||
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<osgGA::CameraManipulator> 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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -32,7 +32,6 @@
|
||||
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Node>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/Vec3d>
|
||||
|
||||
#include <osgGA/CameraManipulator>
|
||||
@ -96,30 +95,15 @@ private:
|
||||
osg::ref_ptr<osg::Node> 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<osg::NodeCallback> nodeUpdateCallback;
|
||||
|
||||
osg::Matrix cameraPosition;
|
||||
osg::Matrix cameraRotation;
|
||||
|
||||
bool dirty;
|
||||
|
||||
public:
|
||||
osg::ref_ptr<MyManipulator> 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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 \
|
||||
|
Loading…
x
Reference in New Issue
Block a user