mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-21 11:54:15 +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";
|
qDebug() << "OSGCamera::updateClearColor - invalid camera";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// qDebug() << "OSGCamera::updateClearColor" << clearColor;
|
||||||
qDebug() << "OSGCamera::updateClearColor" << clearColor;
|
|
||||||
|
|
||||||
camera->setClearColor(osg::Vec4(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF()));
|
camera->setClearColor(osg::Vec4(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,11 +143,12 @@ public:
|
|||||||
|
|
||||||
void updateLogDepthBuffer()
|
void updateLogDepthBuffer()
|
||||||
{
|
{
|
||||||
qDebug() << "OSGCamera::updateLogDepthBuffer" << logDepthBufferEnabled;
|
|
||||||
if (!camera.valid()) {
|
if (!camera.valid()) {
|
||||||
qWarning() << "OSGCamera::updateLogDepthBuffer - invalid camera";
|
qWarning() << "OSGCamera::updateLogDepthBuffer - invalid camera";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// qDebug() << "OSGCamera::updateLogDepthBuffer" << logDepthBufferEnabled;
|
||||||
|
|
||||||
#ifdef USE_OSGEARTH
|
#ifdef USE_OSGEARTH
|
||||||
// install log depth buffer if requested
|
// install log depth buffer if requested
|
||||||
if (logDepthBufferEnabled && !logDepthBuffer) {
|
if (logDepthBufferEnabled && !logDepthBuffer) {
|
||||||
|
@ -144,7 +144,7 @@ public:
|
|||||||
|
|
||||||
void updatePosition()
|
void updatePosition()
|
||||||
{
|
{
|
||||||
qDebug() << "OSGGeoTransformNode::updatePosition" << position;
|
// qDebug() << "OSGGeoTransformNode::updatePosition" << position;
|
||||||
|
|
||||||
osgEarth::MapNode *mapNode = NULL;
|
osgEarth::MapNode *mapNode = NULL;
|
||||||
if (sceneNode && sceneNode->node()) {
|
if (sceneNode && sceneNode->node()) {
|
||||||
|
@ -27,27 +27,16 @@
|
|||||||
|
|
||||||
#include "OSGNode.hpp"
|
#include "OSGNode.hpp"
|
||||||
|
|
||||||
|
#include "DirtySupport.hpp"
|
||||||
|
|
||||||
#include <osg/Node>
|
#include <osg/Node>
|
||||||
#include <osg/NodeVisitor>
|
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
namespace osgQtQuick {
|
namespace osgQtQuick {
|
||||||
class OSGNode;
|
class OSGNode;
|
||||||
class Hidden;
|
|
||||||
|
|
||||||
struct OSGNode::NodeUpdateCallback : public osg::NodeCallback {
|
struct OSGNode::Hidden : public QObject, public DirtySupport {
|
||||||
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 {
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
friend class OSGNode;
|
friend class OSGNode;
|
||||||
@ -57,48 +46,20 @@ private:
|
|||||||
|
|
||||||
osg::ref_ptr<osg::Node> node;
|
osg::ref_ptr<osg::Node> node;
|
||||||
|
|
||||||
osg::ref_ptr<osg::NodeCallback> nodeUpdateCallback;
|
|
||||||
|
|
||||||
bool complete;
|
bool complete;
|
||||||
int dirty;
|
|
||||||
|
|
||||||
public:
|
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;
|
return self->node();
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update()
|
void update()
|
||||||
{
|
{
|
||||||
if (dirty) {
|
return self->update();
|
||||||
self->update();
|
|
||||||
}
|
|
||||||
clearDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool acceptNode(osg::Node *aNode)
|
bool acceptNode(osg::Node *aNode)
|
||||||
@ -106,32 +67,21 @@ public:
|
|||||||
if (node == aNode) {
|
if (node == aNode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (node && dirty) {
|
|
||||||
node->setUpdateCallback(NULL);
|
int flags = dirty();
|
||||||
|
if (flags) {
|
||||||
|
clearDirty();
|
||||||
}
|
}
|
||||||
node = aNode;
|
node = aNode;
|
||||||
if (node) {
|
if (node) {
|
||||||
if (dirty) {
|
if (flags) {
|
||||||
if (!nodeUpdateCallback.valid()) {
|
setDirty(flags);
|
||||||
// lazy creation
|
|
||||||
nodeUpdateCallback = new NodeUpdateCallback(this);
|
|
||||||
}
|
|
||||||
node->setUpdateCallback(nodeUpdateCallback);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
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 */
|
/* class OSGNode */
|
||||||
|
|
||||||
OSGNode::OSGNode(QObject *parent) : QObject(parent), QQmlParserStatus(), h(new Hidden(this))
|
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
|
bool OSGNode::isDirty(int mask) const
|
||||||
{
|
{
|
||||||
return h->isDirty(mask);
|
return h->isDirty(mask);
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
* - node change events should be handled right away.
|
* - node change events should be handled right away.
|
||||||
*
|
*
|
||||||
* Setting an OSGNode dirty will trigger the addition of a one time update callback.
|
* Setting an OSGNode dirty will trigger the addition of a one time update callback.
|
||||||
* *
|
|
||||||
* This approach leads to some potential issues:
|
* 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).
|
* - 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_OBJECT
|
||||||
Q_INTERFACES(QQmlParserStatus)
|
Q_INTERFACES(QQmlParserStatus)
|
||||||
|
|
||||||
friend class OSGViewport;
|
|
||||||
friend class NodeUpdateCallback;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit OSGNode(QObject *parent = 0);
|
explicit OSGNode(QObject *parent = 0);
|
||||||
virtual ~OSGNode();
|
virtual ~OSGNode();
|
||||||
@ -66,9 +62,8 @@ public:
|
|||||||
void setNode(osg::Node *node);
|
void setNode(osg::Node *node);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool isDirty() const;
|
bool isDirty(int mask = 0xFFFF) const;
|
||||||
bool isDirty(int mask) const;
|
void setDirty(int mask = 0xFFFF);
|
||||||
void setDirty(int mask);
|
|
||||||
void clearDirty();
|
void clearDirty();
|
||||||
|
|
||||||
void classBegin();
|
void classBegin();
|
||||||
@ -83,7 +78,6 @@ signals:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
struct Hidden;
|
struct Hidden;
|
||||||
struct NodeUpdateCallback;
|
|
||||||
Hidden *const h;
|
Hidden *const h;
|
||||||
|
|
||||||
virtual void update();
|
virtual void update();
|
||||||
|
@ -102,7 +102,7 @@ public:
|
|||||||
|
|
||||||
void updateScale()
|
void updateScale()
|
||||||
{
|
{
|
||||||
qDebug() << "OSGTransformNode::updateScale" << scale;
|
// qDebug() << "OSGTransformNode::updateScale" << scale;
|
||||||
if ((scale.x() != 0.0) || (scale.y() != 0.0) || (scale.z() != 0.0)) {
|
if ((scale.x() != 0.0) || (scale.y() != 0.0) || (scale.z() != 0.0)) {
|
||||||
transform->setScale(osg::Vec3d(scale.x(), scale.y(), scale.z()));
|
transform->setScale(osg::Vec3d(scale.x(), scale.y(), scale.z()));
|
||||||
// transform->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
|
// 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. *
|
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
|
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 {
|
namespace osgQtQuick {
|
||||||
enum DirtyFlag { Scene = 1 << 0, Camera = 1 << 1 };
|
enum DirtyFlag { Scene = 1 << 0, Camera = 1 << 1 };
|
||||||
@ -93,7 +116,6 @@ private:
|
|||||||
|
|
||||||
osg::ref_ptr<osg::GraphicsContext> gc;
|
osg::ref_ptr<osg::GraphicsContext> gc;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OSGNode *sceneNode;
|
OSGNode *sceneNode;
|
||||||
OSGCamera *cameraNode;
|
OSGCamera *cameraNode;
|
||||||
@ -483,12 +505,12 @@ public:
|
|||||||
|
|
||||||
osg::Viewport *viewport = h->view->getCamera()->getViewport();
|
osg::Viewport *viewport = h->view->getCamera()->getViewport();
|
||||||
if ((viewport->width() != item->width()) || (viewport->height() != item->height())) {
|
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;
|
needToDoFrame = true;
|
||||||
|
|
||||||
// h->view->getCamera()->resize(item->width(), item->height());
|
// h->view->getCamera()->resize(item->width(), item->height());
|
||||||
int dpr = h->self->window()->devicePixelRatio();
|
int dpr = h->self->window()->devicePixelRatio();
|
||||||
h->view->getCamera()->getGraphicsContext()->resized(0, 0, item->width() * dpr, item->height() * dpr);
|
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
|
// trick to force a "home" on first few frames to absorb initial spurious resizes
|
||||||
if (frameCount <= 2) {
|
if (frameCount <= 2) {
|
||||||
@ -498,16 +520,11 @@ public:
|
|||||||
|
|
||||||
// refresh busy state
|
// refresh busy state
|
||||||
h->self->setBusy(h->view->getDatabasePager()->getRequestsInProgress());
|
h->self->setBusy(h->view->getDatabasePager()->getRequestsInProgress());
|
||||||
|
|
||||||
// TODO also expose request list size to Qml
|
// TODO also expose request list size to Qml
|
||||||
if (h->view->getDatabasePager()->getFileRequestListSize() > 0) {
|
if (h->view->getDatabasePager()->getFileRequestListSize() > 0) {
|
||||||
// qDebug() << h->view->getDatabasePager()->getFileRequestListSize();
|
// 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) {
|
if (!needToDoFrame) {
|
||||||
needToDoFrame = h->viewer->checkNeedToDoFrame();
|
needToDoFrame = h->viewer->checkNeedToDoFrame();
|
||||||
}
|
}
|
||||||
@ -520,31 +537,12 @@ public:
|
|||||||
}
|
}
|
||||||
if (needToDoFrame) {
|
if (needToDoFrame) {
|
||||||
// qDebug() << "ViewportRenderer::synchronize - update scene" << frameCount;
|
// qDebug() << "ViewportRenderer::synchronize - update scene" << frameCount;
|
||||||
|
|
||||||
// info();
|
|
||||||
h->viewer->advance();
|
h->viewer->advance();
|
||||||
h->viewer->eventTraversal();
|
h->viewer->eventTraversal();
|
||||||
h->viewer->updateTraversal();
|
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.
|
// 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.
|
// The framebuffer is bound at this point and the glViewport has been set up to match the FBO size.
|
||||||
void render()
|
void render()
|
||||||
@ -581,34 +579,7 @@ public:
|
|||||||
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
|
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
|
||||||
// format.setSamples(4);
|
// format.setSamples(4);
|
||||||
|
|
||||||
/**
|
QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(size.width(), size.height(), format);
|
||||||
* 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);
|
|
||||||
|
|
||||||
return fbo;
|
return fbo;
|
||||||
}
|
}
|
||||||
@ -731,7 +702,7 @@ QSGNode *OSGViewport::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode
|
|||||||
{
|
{
|
||||||
// qDebug() << "OSGViewport::updatePaintNode";
|
// qDebug() << "OSGViewport::updatePaintNode";
|
||||||
if (!node) {
|
if (!node) {
|
||||||
qDebug() << "OSGViewport::updatePaintNode - set transform";
|
// qDebug() << "OSGViewport::updatePaintNode - set transform";
|
||||||
node = QQuickFramebufferObject::updatePaintNode(node, nodeData);
|
node = QQuickFramebufferObject::updatePaintNode(node, nodeData);
|
||||||
QSGSimpleTextureNode *n = static_cast<QSGSimpleTextureNode *>(node);
|
QSGSimpleTextureNode *n = static_cast<QSGSimpleTextureNode *>(node);
|
||||||
return 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(osgQtQuick::UpdateMode::Enum updateMode READ updateMode WRITE setUpdateMode NOTIFY updateModeChanged)
|
||||||
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
||||||
|
|
||||||
public:
|
|
||||||
friend class ViewportRenderer;
|
friend class ViewportRenderer;
|
||||||
|
|
||||||
|
public:
|
||||||
explicit OSGViewport(QQuickItem *parent = 0);
|
explicit OSGViewport(QQuickItem *parent = 0);
|
||||||
virtual ~OSGViewport();
|
virtual ~OSGViewport();
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "OSGCameraManipulator.hpp"
|
#include "OSGCameraManipulator.hpp"
|
||||||
|
|
||||||
|
#include "../DirtySupport.hpp"
|
||||||
#include "../OSGNode.hpp"
|
#include "../OSGNode.hpp"
|
||||||
|
|
||||||
#include <osgGA/CameraManipulator>
|
#include <osgGA/CameraManipulator>
|
||||||
@ -34,11 +35,13 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
namespace osgQtQuick {
|
namespace osgQtQuick {
|
||||||
struct OSGCameraManipulator::Hidden : public QObject {
|
struct OSGCameraManipulator::Hidden : public QObject, public DirtySupport {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class OSGCameraManipulator;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OSGCameraManipulator * const self;
|
OSGCameraManipulator *const self;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
osg::ref_ptr<osgGA::CameraManipulator> manipulator;
|
osg::ref_ptr<osgGA::CameraManipulator> manipulator;
|
||||||
@ -52,6 +55,16 @@ public:
|
|||||||
~Hidden()
|
~Hidden()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
osg::Node *hookNode() const
|
||||||
|
{
|
||||||
|
return manipulator->getNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void update()
|
||||||
|
{
|
||||||
|
return self->update();
|
||||||
|
}
|
||||||
|
|
||||||
bool acceptSceneNode(OSGNode *node)
|
bool acceptSceneNode(OSGNode *node)
|
||||||
{
|
{
|
||||||
qDebug() << "OSGCameraManipulator::acceptSceneNode" << 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()
|
void OSGCameraManipulator::classBegin()
|
||||||
{
|
{
|
||||||
// qDebug() << "OSGCameraManipulator::classBegin" << this;
|
// qDebug() << "OSGCameraManipulator::classBegin" << this;
|
||||||
@ -138,6 +166,9 @@ osgGA::CameraManipulator *OSGCameraManipulator::asCameraManipulator() const
|
|||||||
{
|
{
|
||||||
return h->manipulator;
|
return h->manipulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OSGCameraManipulator::update()
|
||||||
|
{}
|
||||||
} // namespace osgQtQuick
|
} // namespace osgQtQuick
|
||||||
|
|
||||||
#include "OSGCameraManipulator.moc"
|
#include "OSGCameraManipulator.moc"
|
||||||
|
@ -59,6 +59,10 @@ signals:
|
|||||||
void sceneNodeChanged(OSGNode *node);
|
void sceneNodeChanged(OSGNode *node);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool isDirty(int mask = 0xFFFF) const;
|
||||||
|
void setDirty(int mask = 0xFFFF);
|
||||||
|
void clearDirty();
|
||||||
|
|
||||||
void classBegin();
|
void classBegin();
|
||||||
void componentComplete();
|
void componentComplete();
|
||||||
|
|
||||||
@ -68,6 +72,8 @@ protected:
|
|||||||
private:
|
private:
|
||||||
struct Hidden;
|
struct Hidden;
|
||||||
Hidden *const h;
|
Hidden *const h;
|
||||||
|
|
||||||
|
virtual void update();
|
||||||
};
|
};
|
||||||
} // namespace osgQtQuick
|
} // namespace osgQtQuick
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
|
|
||||||
#include <osg/Matrix>
|
#include <osg/Matrix>
|
||||||
#include <osg/Node>
|
#include <osg/Node>
|
||||||
#include <osg/NodeVisitor>
|
|
||||||
#include <osg/Vec3d>
|
#include <osg/Vec3d>
|
||||||
|
|
||||||
#include <osgGA/CameraManipulator>
|
#include <osgGA/CameraManipulator>
|
||||||
@ -96,30 +95,15 @@ private:
|
|||||||
osg::ref_ptr<osg::Node> node;
|
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 {
|
struct OSGGeoTransformManipulator::Hidden : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OSGGeoTransformManipulator * const self;
|
OSGGeoTransformManipulator * const self;
|
||||||
|
|
||||||
osg::ref_ptr<osg::NodeCallback> nodeUpdateCallback;
|
|
||||||
|
|
||||||
osg::Matrix cameraPosition;
|
osg::Matrix cameraPosition;
|
||||||
osg::Matrix cameraRotation;
|
osg::Matrix cameraRotation;
|
||||||
|
|
||||||
bool dirty;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
osg::ref_ptr<MyManipulator> manipulator;
|
osg::ref_ptr<MyManipulator> manipulator;
|
||||||
|
|
||||||
@ -129,7 +113,7 @@ public:
|
|||||||
bool clampToTerrain;
|
bool clampToTerrain;
|
||||||
bool intoTerrain;
|
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();
|
manipulator = new MyManipulator();
|
||||||
self->setManipulator(manipulator);
|
self->setManipulator(manipulator);
|
||||||
@ -138,45 +122,6 @@ public:
|
|||||||
~Hidden()
|
~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()
|
void updateManipulator()
|
||||||
{
|
{
|
||||||
// qDebug() << "OSGGeoTransformManipulator::updateManipulator";
|
// qDebug() << "OSGGeoTransformManipulator::updateManipulator";
|
||||||
@ -256,16 +201,6 @@ void MyManipulator::updateCamera(osg::Camera & camera)
|
|||||||
CameraManipulator::updateCamera(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 */
|
/* class OSGGeoTransformManipulator */
|
||||||
|
|
||||||
OSGGeoTransformManipulator::OSGGeoTransformManipulator(QObject *parent) : OSGCameraManipulator(parent), h(new Hidden(this))
|
OSGGeoTransformManipulator::OSGGeoTransformManipulator(QObject *parent) : OSGCameraManipulator(parent), h(new Hidden(this))
|
||||||
@ -304,7 +239,7 @@ void OSGGeoTransformManipulator::setAttitude(QVector3D arg)
|
|||||||
{
|
{
|
||||||
if (h->attitude != arg) {
|
if (h->attitude != arg) {
|
||||||
h->attitude = arg;
|
h->attitude = arg;
|
||||||
h->setDirty();
|
setDirty();
|
||||||
emit attitudeChanged(attitude());
|
emit attitudeChanged(attitude());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,7 +253,7 @@ void OSGGeoTransformManipulator::setPosition(QVector3D arg)
|
|||||||
{
|
{
|
||||||
if (h->position != arg) {
|
if (h->position != arg) {
|
||||||
h->position = arg;
|
h->position = arg;
|
||||||
h->setDirty();
|
setDirty();
|
||||||
emit positionChanged(position());
|
emit positionChanged(position());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -329,8 +264,15 @@ void OSGGeoTransformManipulator::componentComplete()
|
|||||||
OSGCameraManipulator::componentComplete();
|
OSGCameraManipulator::componentComplete();
|
||||||
|
|
||||||
qDebug() << "OSGGeoTransformManipulator::componentComplete" << this;
|
qDebug() << "OSGGeoTransformManipulator::componentComplete" << this;
|
||||||
h->update();
|
update();
|
||||||
h->clearDirty();
|
clearDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSGGeoTransformManipulator::update()
|
||||||
|
{
|
||||||
|
h->updatePosition();
|
||||||
|
h->updateAttitude();
|
||||||
|
h->updateManipulator();
|
||||||
}
|
}
|
||||||
} // namespace osgQtQuick
|
} // 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 clampToTerrain READ clampToTerrain WRITE setClampToTerrain NOTIFY clampToTerrainChanged)
|
||||||
Q_PROPERTY(bool intoTerrain READ intoTerrain NOTIFY intoTerrainChanged)
|
Q_PROPERTY(bool intoTerrain READ intoTerrain NOTIFY intoTerrainChanged)
|
||||||
|
|
||||||
friend class NodeUpdateCallback;
|
|
||||||
friend class MyManipulator;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit OSGGeoTransformManipulator(QObject *parent = 0);
|
explicit OSGGeoTransformManipulator(QObject *parent = 0);
|
||||||
virtual ~OSGGeoTransformManipulator();
|
virtual ~OSGGeoTransformManipulator();
|
||||||
@ -70,8 +67,9 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
struct Hidden;
|
struct Hidden;
|
||||||
struct NodeUpdateCallback;
|
|
||||||
Hidden *const h;
|
Hidden *const h;
|
||||||
|
|
||||||
|
virtual void update();
|
||||||
};
|
};
|
||||||
} // namespace osgQtQuick
|
} // namespace osgQtQuick
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ SOURCES += \
|
|||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
osgQtQuick/Export.hpp \
|
osgQtQuick/Export.hpp \
|
||||||
|
osgQtQuick/DirtySupport.hpp \
|
||||||
osgQtQuick/OSGNode.hpp \
|
osgQtQuick/OSGNode.hpp \
|
||||||
osgQtQuick/OSGGroup.hpp \
|
osgQtQuick/OSGGroup.hpp \
|
||||||
osgQtQuick/OSGTransformNode.hpp \
|
osgQtQuick/OSGTransformNode.hpp \
|
||||||
@ -59,6 +60,7 @@ HEADERS += \
|
|||||||
osgQtQuick/OSGViewport.hpp
|
osgQtQuick/OSGViewport.hpp
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
osgQtQuick/DirtySupport.cpp \
|
||||||
osgQtQuick/OSGNode.cpp \
|
osgQtQuick/OSGNode.cpp \
|
||||||
osgQtQuick/OSGGroup.cpp \
|
osgQtQuick/OSGGroup.cpp \
|
||||||
osgQtQuick/OSGTransformNode.cpp \
|
osgQtQuick/OSGTransformNode.cpp \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user