1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-19 04:52:12 +01:00

Merged in filnet/librepilot/filnet/LP-29_osgearth_integration (pull request #192)

Filnet/lp 29_osgearth_integration
This commit is contained in:
Philippe Renon 2016-03-12 12:39:31 +01:00
commit 0b79fe9e6f
45 changed files with 1303 additions and 1089 deletions

View File

@ -38,30 +38,20 @@ namespace osgQtQuick {
struct OSGBackgroundNode::Hidden : public QObject {
Q_OBJECT
private:
OSGBackgroundNode * const self;
public:
QUrl url;
Hidden(OSGBackgroundNode *parent) : QObject(parent), self(parent), url() {}
bool acceptImageFile(QUrl url)
void updateNode()
{
// qDebug() << "OSGBackgroundNode::acceptImageFile" << url;
if (this->url == url) {
return false;
}
this->url = url;
realize();
return true;
}
void realize()
{
qDebug() << "OSGBackgroundNode::realize";
// qDebug() << "OSGBackgroundNode::realize - reading image file" << h->url.path();
// qDebug() << "OSGBackgroundNode::realize - reading image file" << url.path();
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
osg::ref_ptr<osg::Image> image = osgDB::readImageFile(url.path().toStdString());
osg::ref_ptr<osg::Image> image = osgDB::readImageFile(url.path().toStdString());
texture->setImage(image.get());
osg::ref_ptr<osg::Drawable> quad = osg::createTexturedQuadGeometry(
@ -86,20 +76,21 @@ public:
self->setNode(camera);
}
OSGBackgroundNode *const self;
QUrl url;
};
/* class OSGBackgroundNode */
enum DirtyFlag { URL = 1 << 0 };
OSGBackgroundNode::OSGBackgroundNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
// qDebug() << "OSGBackgroundNode::OSGBackgroundNode";
qDebug() << "OSGBackgroundNode::OSGBackgroundNode";
}
OSGBackgroundNode::~OSGBackgroundNode()
{
// qDebug() << "OSGBackgroundNode::~OSGBackgroundNode";
delete h;
}
const QUrl OSGBackgroundNode::imageFile() const
@ -110,10 +101,28 @@ const QUrl OSGBackgroundNode::imageFile() const
void OSGBackgroundNode::setImageFile(const QUrl &url)
{
// qDebug() << "OSGBackgroundNode::setImageFile" << url;
if (h->acceptImageFile(url)) {
emit imageFileChanged(imageFile());
if (h->url != url) {
h->url = url;
setDirty(URL);
emit imageFileChanged(url);
}
}
void OSGBackgroundNode::update()
{
if (isDirty(URL)) {
h->updateNode();
}
}
void OSGBackgroundNode::attach(osgViewer::View *view)
{
update();
clearDirty();
}
void OSGBackgroundNode::detach(osgViewer::View *view)
{}
} // namespace osgQtQuick
#include "OSGBackgroundNode.moc"

View File

@ -53,6 +53,11 @@ signals:
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -54,29 +54,13 @@ 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 +77,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 +109,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 +134,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 +146,7 @@ public:
}
#endif
dirty = true;
fovDirty = true;
updateCamera();
updateFieldOfView();
updateAspectRatio();
}
@ -203,11 +160,6 @@ public:
}
this->camera = NULL;
if (cameraUpdateCallback.valid()) {
camera->removeUpdateCallback(cameraUpdateCallback);
cameraUpdateCallback = NULL;
}
#ifdef USE_OSGEARTH
if (logDepthBuffer) {
logDepthBuffer->uninstall(camera);
@ -283,11 +235,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 +253,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 +276,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 +294,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 {
@ -384,25 +321,26 @@ public:
osg::Matrix cameraMatrix = cameraRotation
* osg::Matrix::rotate(roll, osg::Vec3(0, 1, 0))
* osg::Matrix::rotate(pitch, osg::Vec3(1, 0, 0))
* osg::Matrix::rotate(yaw, osg::Vec3(0, 0, -1.0)) * cameraPosition;
* osg::Matrix::rotate(yaw, osg::Vec3(0, 0, -1)) * cameraPosition;
// Inverse the camera's position and orientation matrix to obtain the view matrix
cameraMatrix = osg::Matrix::inverse(cameraMatrix);
camera->setViewMatrix(cameraMatrix);
}
qreal fieldOfView;
bool fovDirty;
OSGCamera *const self;
OSGNode *sceneData;
osg::ref_ptr<osg::Camera> camera;
// Camera vertical field of view in degrees
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,11 @@ 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))
enum DirtyFlag { FieldOfView = 1 << 0, Position = 1 << 1, Attitude = 1 << 2 };
OSGCamera::OSGCamera(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
qDebug() << "OSGCamera::OSGCamera";
}
@ -455,6 +380,7 @@ OSGCamera::OSGCamera(QObject *parent) : QObject(parent), h(new Hidden(this))
OSGCamera::~OSGCamera()
{
qDebug() << "OSGCamera::~OSGCamera";
delete h;
}
qreal OSGCamera::fieldOfView() const
@ -462,25 +388,24 @@ qreal OSGCamera::fieldOfView() const
return h->fieldOfView;
}
// Camera vertical field of view in degrees
void OSGCamera::setFieldOfView(qreal arg)
{
if (h->fieldOfView != arg) {
h->fieldOfView = arg;
h->fovDirty = true;
setDirty(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 +421,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 +455,6 @@ void OSGCamera::setClampToTerrain(bool arg)
{
if (h->clampToTerrain != arg) {
h->clampToTerrain = arg;
h->dirty = true;
emit clampToTerrainChanged(clampToTerrain());
}
}
@ -561,7 +473,7 @@ void OSGCamera::setAttitude(QVector3D arg)
{
if (h->attitude != arg) {
h->attitude = arg;
h->dirty = true;
setDirty(Attitude);
emit attitudeChanged(attitude());
}
}
@ -575,7 +487,7 @@ void OSGCamera::setPosition(QVector3D arg)
{
if (h->position != arg) {
h->position = arg;
h->dirty = true;
setDirty(Position);
emit positionChanged(position());
}
}
@ -593,16 +505,28 @@ void OSGCamera::setLogarithmicDepthBuffer(bool enabled)
}
}
void OSGCamera::update()
{
if (isDirty(FieldOfView)) {
h->updateFieldOfView();
}
if (isDirty(Position | Attitude)) {
h->updatePosition();
}
}
void OSGCamera::attach(osgViewer::View *view)
{
h->attachCamera(view->getCamera());
h->attachManipulator(view);
update();
clearDirty();
}
void OSGCamera::detach(osgViewer::View *view)
{
h->detachCamera(view->getCamera());
h->detachManipulator(view);
h->detachCamera(view->getCamera());
}
} // namespace osgQtQuick

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,8 @@ 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)
friend class OSGViewport;
public:
explicit OSGCamera(QObject *parent = 0);
virtual ~OSGCamera();
@ -88,15 +88,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);
@ -117,18 +114,13 @@ public:
bool logarithmicDepthBuffer();
void setLogarithmicDepthBuffer(bool enabled);
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
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 +135,11 @@ signals:
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -45,10 +45,11 @@ public:
void run()
{
load();
osg::Node *node = load();
emit loaded(url, node);
}
void load()
osg::Node *load()
{
QElapsedTimer t;
@ -57,8 +58,7 @@ public:
// qDebug() << "OSGFileLoader - load - currentContext" << QOpenGLContext::currentContext();
osg::Node *node = osgDB::readNodeFile(url.path().toStdString());
// qDebug() << "OSGFileLoader::load - reading node" << node << "took" << t.elapsed() << "ms";
emit loaded(url, node);
return node;
}
signals:
@ -75,33 +75,37 @@ private:
OSGFileNode * const self;
public:
Hidden(OSGFileNode *parent) : QObject(parent), self(parent), url(), async(false), optimizeMode(OptimizeMode::None) {}
bool acceptSource(QUrl url)
{
// qDebug() << "OSGFileNode::acceptSource" << url;
if (this->url == url) {
return false;
}
this->url = url;
if (url.isValid()) {
realize();
} else {
qWarning() << "OSGFileNode::acceptNode - invalid url" << url;
self->setNode(NULL);
}
return true;
}
QUrl url;
QUrl source;
bool async;
OptimizeMode::Enum optimizeMode;
Hidden(OSGFileNode *node) : QObject(node), self(node), source(), async(false), optimizeMode(OptimizeMode::None) {}
void updateNode()
{
// qDebug() << "OSGFileNode::updateNode" << source;
if (!source.isValid()) {
self->setNode(NULL);
if (!source.isEmpty()) {
qWarning() << "OSGFileNode::updateNode - invalid source" << source;
}
}
if (false /*async*/) {
// not supported yet
// it is not clear if thread safety is insured...
asyncLoad(source);
} else {
setNode(syncLoad(source));
}
}
private:
osg::Node *syncLoad(const QUrl &url)
{
OSGFileLoader loader(url);
return loader.load();
}
void asyncLoad(const QUrl &url)
{
@ -112,63 +116,56 @@ private:
loader->start();
}
void syncLoad(const QUrl &url)
void setNode(osg::Node *node)
{
OSGFileLoader loader(url);
connect(&loader, &OSGFileLoader::loaded, this, &Hidden::onLoaded);
loader.load();
}
void realize()
{
qDebug() << "OSGFileNode::realize";
if (async) {
asyncLoad(url);
} else {
syncLoad(url);
}
}
bool acceptNode(osg::Node *node)
{
qDebug() << "OSGFileNode::acceptNode" << node;
qDebug() << "OSGFileNode::setNode" << node;
if (node && optimizeMode != OptimizeMode::None) {
// qDebug() << "OSGFileNode::acceptNode - optimize" << node << optimizeMode;
osgUtil::Optimizer optimizer;
optimizer.optimize(node, osgUtil::Optimizer::DEFAULT_OPTIMIZATIONS);
}
self->setNode(node);
return true;
}
private slots:
void onLoaded(const QUrl &url, osg::Node *node)
{
acceptNode(node);
// called in async mode
// question : is it thread safe to call setNode() ?
// could calling setDirty help? is setDirty() thread safe ?
setNode(node);
}
};
/* class OSGFileNode */
enum DirtyFlag { Source = 1 << 0, Async = 1 << 1, OptimizeMode = 1 << 2 };
OSGFileNode::OSGFileNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
qDebug() << "OSGFileNode::OSGFileNode";
setAsync(false);
setOptimizeMode(OptimizeMode::None);
}
OSGFileNode::~OSGFileNode()
{
qDebug() << "OSGFileNode::~OSGFileNode";
// qDebug() << "OSGFileNode::~OSGFileNode";
delete h;
}
const QUrl OSGFileNode::source() const
{
return h->url;
return h->source;
}
void OSGFileNode::setSource(const QUrl &url)
void OSGFileNode::setSource(const QUrl &source)
{
qDebug() << "OSGFileNode::setSource" << url;
if (h->acceptSource(url)) {
emit sourceChanged(source());
qDebug() << "OSGFileNode::setSource" << source;
if (h->source != source) {
h->source = source;
setDirty(Source);
emit sourceChanged(source);
}
}
@ -182,6 +179,7 @@ void OSGFileNode::setAsync(const bool async)
// qDebug() << "OSGFileNode::setAsync" << async;
if (h->async != async) {
h->async = async;
setDirty(Async);
emit asyncChanged(async);
}
}
@ -191,14 +189,37 @@ OptimizeMode::Enum OSGFileNode::optimizeMode() const
return h->optimizeMode;
}
void OSGFileNode::setOptimizeMode(OptimizeMode::Enum mode)
void OSGFileNode::setOptimizeMode(OptimizeMode::Enum optimizeMode)
{
// qDebug() << "OSGFileNode::setOptimizeMode" << mode;
if (h->optimizeMode != mode) {
h->optimizeMode = mode;
emit optimizeModeChanged(optimizeMode());
// qDebug() << "OSGFileNode::setOptimizeMode" << optimizeMode;
if (h->optimizeMode != optimizeMode) {
h->optimizeMode = optimizeMode;
setDirty(OptimizeMode);
emit optimizeModeChanged(optimizeMode);
}
}
void OSGFileNode::update()
{
if (isDirty(Async)) {
// do nothing...
}
if (isDirty(OptimizeMode)) {
// TODO: trigger a node update ?
}
if (isDirty(Source)) {
h->updateNode();
}
}
void OSGFileNode::attach(osgViewer::View *view)
{
update();
clearDirty();
}
void OSGFileNode::detach(osgViewer::View *view)
{}
} // namespace osgQtQuick
#include "OSGFileNode.moc"

View File

@ -50,7 +50,6 @@ class OSGQTQUICK_EXPORT OSGFileNode : public OSGNode {
Q_PROPERTY(osgQtQuick::OptimizeMode::Enum optimizeMode READ optimizeMode WRITE setOptimizeMode NOTIFY optimizeModeChanged)
public:
OSGFileNode(QObject *parent = 0);
virtual ~OSGFileNode();
@ -71,6 +70,11 @@ signals:
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -0,0 +1,291 @@
/**
******************************************************************************
*
* @file OSGGeoTransformNode.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 "OSGGeoTransformNode.hpp"
#include "../utility.h"
#include <osg/ComputeBoundsVisitor>
#include <osgearth/GeoTransform>
#include <osgEarth/MapNode>
#include <osgEarth/GeoData>
#include <QDebug>
namespace osgQtQuick {
struct OSGGeoTransformNode::Hidden : public QObject {
Q_OBJECT
private:
OSGGeoTransformNode * const self;
osg::ref_ptr<osgEarth::GeoTransform> transform;
public:
OSGNode *childNode;
OSGNode *sceneNode;
float offset;
bool clampToTerrain;
bool intoTerrain;
QVector3D position;
Hidden(OSGGeoTransformNode *node) : QObject(node), self(node), childNode(NULL), sceneNode(NULL), offset(-1.0), clampToTerrain(false), intoTerrain(false)
{
transform = new osgEarth::GeoTransform();
transform->setAutoRecomputeHeights(true);
self->setNode(transform);
}
bool acceptChildNode(OSGNode *node)
{
qDebug() << "OSGGeoTransformNode::acceptChildNode" << node;
if (childNode == node) {
return false;
}
if (childNode) {
disconnect(childNode);
}
childNode = node;
if (childNode) {
connect(childNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onChildNodeChanged(osg::Node *)));
}
return true;
}
bool acceptSceneNode(OSGNode *node)
{
qDebug() << "OSGGeoTransformNode::acceptSceneNode" << node;
if (sceneNode == node) {
return false;
}
if (sceneNode) {
disconnect(sceneNode);
}
sceneNode = node;
if (sceneNode) {
connect(sceneNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onSceneNodeChanged(osg::Node *)));
}
return true;
}
void updateTransformNode()
{
bool updated = false;
if (transform->getNumChildren() == 0) {
if (childNode && childNode->node()) {
updated |= transform->addChild(childNode->node());
}
} else {
if (childNode && childNode->node()) {
if (transform->getChild(0) != childNode->node()) {
updated |= transform->removeChild(0, 1);
updated |= transform->addChild(childNode->node());
}
} else {
updated |= transform->removeChild(0, 1);
}
}
// if (updated) {
self->emitNodeChanged();
// }
}
void updateSceneNode()
{
if (sceneNode && sceneNode->node()) {
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
if (mapNode) {
transform->setTerrain(mapNode->getTerrain());
} else {
qWarning() << "OSGGeoTransformNode::updateScene - scene data does not contain a map node";
}
}
}
void updatePosition()
{
osgEarth::MapNode *mapNode = NULL;
if (sceneNode && sceneNode->node()) {
mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
}
if (!mapNode) {
qWarning() << "OSGGeoTransformNode::updatePosition - scene node does not contain a map node";
}
osgEarth::GeoPoint geoPoint;
if (mapNode) {
geoPoint = osgQtQuick::toGeoPoint(mapNode->getTerrain()->getSRS(), position);
} else {
geoPoint = osgQtQuick::toGeoPoint(position);
}
if (clampToTerrain && mapNode) {
// get "size" of model
// TODO this should be done once only...
osg::ComputeBoundsVisitor cbv;
childNode->node()->accept(cbv);
const osg::BoundingBox & bbox = cbv.getBoundingBox();
offset = bbox.radius();
// qDebug() << "OSGGeoTransformNode::updateNode - offset" << offset;
// clamp model to terrain if needed
intoTerrain = clampGeoPoint(geoPoint, offset, mapNode);
}
transform->setPosition(geoPoint);
}
private slots:
void onChildNodeChanged(osg::Node *node)
{
qDebug() << "OSGGeoTransformNode::onChildNodeChanged" << node;
updateTransformNode();
}
void onSceneNodeChanged(osg::Node *node)
{
qDebug() << "OSGGeoTransformNode::onSceneNodeChanged" << node;
// TODO
}
};
/* class OSGGeoTransformNode */
enum DirtyFlag { Child = 1 << 0, Scene = 1 << 1, Position = 1 << 2, Clamp = 1 << 3 };
OSGGeoTransformNode::OSGGeoTransformNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
qDebug() << "OSGGeoTransformNode::OSGGeoTransformNode";
}
OSGGeoTransformNode::~OSGGeoTransformNode()
{
// qDebug() << "OSGGeoTransformNode::~OSGGeoTransformNode";
delete h;
}
OSGNode *OSGGeoTransformNode::childNode()
{
return h->childNode;
}
void OSGGeoTransformNode::setChildNode(OSGNode *node)
{
if (h->acceptChildNode(node)) {
setDirty(Child);
emit childNodeChanged(node);
}
}
OSGNode *OSGGeoTransformNode::sceneNode()
{
return h->sceneNode;
}
void OSGGeoTransformNode::setSceneNode(OSGNode *node)
{
if (h->acceptSceneNode(node)) {
setDirty(Scene);
emit sceneNodeChanged(node);
}
}
bool OSGGeoTransformNode::clampToTerrain() const
{
return h->clampToTerrain;
}
void OSGGeoTransformNode::setClampToTerrain(bool arg)
{
if (h->clampToTerrain != arg) {
h->clampToTerrain = arg;
setDirty(Clamp);
emit clampToTerrainChanged(clampToTerrain());
}
}
bool OSGGeoTransformNode::intoTerrain() const
{
return h->intoTerrain;
}
QVector3D OSGGeoTransformNode::position() const
{
return h->position;
}
void OSGGeoTransformNode::setPosition(QVector3D arg)
{
if (h->position != arg) {
h->position = arg;
setDirty(Position);
emit positionChanged(position());
}
}
void OSGGeoTransformNode::update()
{
if (isDirty(Child)) {
h->updateTransformNode();
}
if (isDirty(Scene)) {
h->updateSceneNode();
}
if (isDirty(Clamp)) {}
if (isDirty(Position)) {
h->updatePosition();
}
}
void OSGGeoTransformNode::attach(osgViewer::View *view)
{
OSGNode::attach(h->childNode, view);
update();
clearDirty();
}
void OSGGeoTransformNode::detach(osgViewer::View *view)
{
OSGNode::detach(h->childNode, view);
}
} // namespace osgQtQuick
#include "OSGGeoTransformNode.moc"

View File

@ -1,7 +1,7 @@
/**
******************************************************************************
*
* @file OSGModelNode.hpp
* @file OSGGeoTransformNode.hpp
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
* @addtogroup
* @{
@ -25,70 +25,65 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _H_OSGQTQUICK_MODELNODE_H_
#define _H_OSGQTQUICK_MODELNODE_H_
#ifndef _H_OSGQTQUICK_GEOTRANSFORMNODE_H_
#define _H_OSGQTQUICK_GEOTRANSFORMNODE_H_
#include "Export.hpp"
#include "OSGNode.hpp"
#include <QVector3D>
#include <QUrl>
namespace osgViewer {
class View;
}
// TODO derive from OSGGroup...
namespace osgQtQuick {
class OSGQTQUICK_EXPORT OSGModelNode : public OSGNode {
class OSGQTQUICK_EXPORT OSGGeoTransformNode : public OSGNode {
Q_OBJECT
// TODO rename to parentNode and modelNode
Q_PROPERTY(osgQtQuick::OSGNode *modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
Q_PROPERTY(osgQtQuick::OSGNode * sceneData READ sceneData WRITE setSceneData NOTIFY sceneDataChanged)
// TODO rename to childNode
Q_PROPERTY(osgQtQuick::OSGNode *modelData READ childNode WRITE setChildNode NOTIFY childNodeChanged)
// TODO rename to sceneNode
Q_PROPERTY(osgQtQuick::OSGNode * sceneData READ sceneNode WRITE setSceneNode NOTIFY sceneNodeChanged)
Q_PROPERTY(bool clampToTerrain READ clampToTerrain WRITE setClampToTerrain NOTIFY clampToTerrainChanged)
Q_PROPERTY(bool intoTerrain READ intoTerrain NOTIFY intoTerrainChanged)
Q_PROPERTY(QVector3D attitude READ attitude WRITE setAttitude NOTIFY attitudeChanged)
Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged)
public:
OSGModelNode(QObject *parent = 0);
virtual ~OSGModelNode();
OSGGeoTransformNode(QObject *parent = 0);
virtual ~OSGGeoTransformNode();
OSGNode *modelData();
void setModelData(OSGNode *node);
OSGNode *childNode();
void setChildNode(OSGNode *node);
OSGNode *sceneData();
void setSceneData(OSGNode *node);
OSGNode *sceneNode();
void setSceneNode(OSGNode *node);
bool clampToTerrain() const;
void setClampToTerrain(bool arg);
bool intoTerrain() const;
QVector3D attitude() const;
void setAttitude(QVector3D arg);
QVector3D position() const;
void setPosition(QVector3D arg);
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
signals:
void modelDataChanged(OSGNode *node);
void sceneDataChanged(OSGNode *node);
void childNodeChanged(OSGNode *node);
void sceneNodeChanged(OSGNode *node);
void clampToTerrainChanged(bool arg);
void intoTerrainChanged(bool arg);
void attitudeChanged(QVector3D arg);
void positionChanged(QVector3D arg);
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick
#endif // _H_OSGQTQUICK_MODELNODE_H_
#endif // _H_OSGQTQUICK_GEOTRANSFORMNODE_H_

View File

@ -33,119 +33,160 @@
#include <QDebug>
namespace osgQtQuick {
enum DirtyFlag { Children = 1 << 0 };
struct OSGGroup::Hidden : public QObject {
Q_OBJECT
public:
Hidden(OSGGroup *parent) : QObject(parent), self(parent)
{
group = new osg::Group;
}
private:
OSGGroup * self;
OSGGroup *self;
osg::ref_ptr<osg::Group> group;
QList<OSGNode *> children;
osg::ref_ptr<osg::Group> group;
QMap<OSGNode *, osg::Node *> cache;
static void append_child(QQmlListProperty<OSGNode> *list, OSGNode *child)
public:
Hidden(OSGGroup *node) : QObject(node), self(node), group(new osg::Group)
{
OSGGroup *group = qobject_cast<OSGGroup *>(list->object);
group = new osg::Group();
self->setNode(group);
}
if (group && child) {
group->h->cache[child] = child->node();
group->h->children.append(child);
if (child->node()) {
group->h->group->addChild(child->node());
emit group->nodeChanged(group->h->group);
}
QObject::connect(child, SIGNAL(nodeChanged(osg::Node *)), group->h, SLOT(onNodeChanged(osg::Node *)));
QList<OSGNode *> children;
void appendChild(OSGNode *childNode)
{
cache[childNode] = childNode->node();
children.append(childNode);
connect(childNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onChildNodeChanged(osg::Node *)), Qt::UniqueConnection);
self->setDirty(Children);
}
int countChild() const
{
return children.size();
}
OSGNode *atChild(int index) const
{
if (index >= 0 && index < children.size()) {
return children[index];
}
return 0;
}
void clearChild()
{
while (!children.isEmpty()) {
OSGNode *node = children.takeLast();
disconnect(node);
}
children.clear();
cache.clear();
self->setDirty(Children);
}
void updateGroupNode()
{
bool updated = false;
unsigned int index = 0;
QListIterator<OSGNode *> i(children);
while (i.hasNext()) {
OSGNode *childNode = i.next();
if (index < group->getNumChildren()) {
updated |= group->replaceChild(group->getChild(index), childNode->node());
} else {
updated |= group->addChild(childNode->node());
}
index++;
}
// removing eventual left overs
if (index < group->getNumChildren()) {
updated |= group->removeChild(index, group->getNumChildren() - index);
}
// if (updated) {
self->emitNodeChanged();
// }
}
/* QQmlListProperty<OSGNode> */
static void append_child(QQmlListProperty<OSGNode> *list, OSGNode *childNode)
{
Hidden *h = qobject_cast<Hidden *>(list->object);
h->appendChild(childNode);
}
static int count_child(QQmlListProperty<OSGNode> *list)
{
OSGGroup *group = qobject_cast<OSGGroup *>(list->object);
Hidden *h = qobject_cast<Hidden *>(list->object);
if (group) {
return group->h->children.size();
}
return 0;
return h->countChild();
}
static OSGNode *at_child(QQmlListProperty<OSGNode> *list, int index)
{
OSGGroup *group = qobject_cast<OSGGroup *>(list->object);
Hidden *h = qobject_cast<Hidden *>(list->object);
if (group && index >= 0 && index < group->h->children.size()) {
return group->h->children[index];
}
return 0;
return h->atChild(index);
}
static void clear_child(QQmlListProperty<OSGNode> *list)
{
OSGGroup *group = qobject_cast<OSGGroup *>(list->object);
Hidden *h = qobject_cast<Hidden *>(list->object);
if (group) {
while (!group->h->children.isEmpty()) {
OSGNode *node = group->h->children.takeLast();
if (node->parent() == group) {
node->deleteLater();
}
if (!node->parent()) {
node->deleteLater();
}
}
group->h->group->removeChild(0, group->h->group->getNumChildren());
group->h->cache.clear();
}
h->clearChild();
}
public slots:
void onNodeChanged(osg::Node *node)
private slots:
void onChildNodeChanged(osg::Node *node)
{
qDebug() << "OSGGroup::nodeChanged" << node;
qDebug() << "OSGGroup::onChildNodeChanged" << node;
OSGNode *obj = qobject_cast<OSGNode *>(sender());
if (obj) {
osg::Node *cacheNode = cache.value(obj, NULL);
if (cacheNode) {
group->removeChild(cacheNode);
}
if (node) {
group->addChild(node);
group->replaceChild(cacheNode, node);
} else {
// should not happen...
}
cache[obj] = node;
emit self->nodeChanged(group.get());
// emit self->nodeChanged(group.get());
}
}
};
OSGGroup::OSGGroup(QObject *parent) :
OSGNode(parent), h(new Hidden(this))
/* class OSGGGroupNode */
OSGGroup::OSGGroup(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
qDebug() << "OSGGroup::OSGGroup";
setNode(h->group.get());
}
OSGGroup::~OSGGroup()
{
qDebug() << "OSGGroup::~OSGGroup";
// qDebug() << "OSGGroup::~OSGGroup";
delete h;
}
QQmlListProperty<OSGNode> OSGGroup::children()
{
return QQmlListProperty<OSGNode>(this, 0,
return QQmlListProperty<OSGNode>(h, 0,
&Hidden::append_child,
&Hidden::count_child,
&Hidden::at_child,
&Hidden::clear_child);
}
void OSGGroup::update()
{
if (isDirty(Children)) {
h->updateGroupNode();
}
}
void OSGGroup::attach(osgViewer::View *view)
{
// qDebug() << "OSGGroup::attach " << view;
@ -153,8 +194,10 @@ void OSGGroup::attach(osgViewer::View *view)
while (i.hasNext()) {
OSGNode *node = i.next();
// qDebug() << "OSGGroup::attach - child" << node;
node->attach(view);
OSGNode::attach(node, view);
}
update();
clearDirty();
}
void OSGGroup::detach(osgViewer::View *view)
@ -164,7 +207,7 @@ void OSGGroup::detach(osgViewer::View *view)
while (i.hasNext()) {
OSGNode *node = i.next();
// qDebug() << "OSGGroup::detach - child" << node;
node->detach(view);
OSGNode::detach(node, view);
}
}
} // namespace osgQtQuick

View File

@ -45,12 +45,14 @@ public:
QQmlListProperty<OSGNode> children();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -1,367 +0,0 @@
/**
******************************************************************************
*
* @file OSGModelNode.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 "OSGModelNode.hpp"
#include "../utility.h"
#include <osg/Quat>
#include <osg/ComputeBoundsVisitor>
#include <osgViewer/View>
#include <osgEarth/MapNode>
#include <osgEarth/GeoData>
#include <osgEarthSymbology/Style>
#include <osgEarthSymbology/ModelSymbol>
#include <osgEarthAnnotation/ModelNode>
#include <QDebug>
namespace osgQtQuick {
struct OSGModelNode::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(OSGModelNode *parent) : QObject(parent), self(parent), modelData(NULL), sceneData(NULL), offset(-1.0), clampToTerrain(false), intoTerrain(false), dirty(false)
{}
~Hidden()
{}
bool acceptModelData(OSGNode *node)
{
qDebug() << "OSGModelNode::acceptModelData" << node;
if (modelData == node) {
return false;
}
if (modelData) {
disconnect(modelData);
}
modelData = node;
if (modelData) {
acceptModelNode(modelData->node());
connect(modelData, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onModelNodeChanged(osg::Node *)));
}
return true;
}
bool acceptModelNode(osg::Node *node)
{
qDebug() << "OSGModelNode::acceptModelNode" << node;
if (!node) {
qWarning() << "OSGModelNode::acceptModelNode - node is null";
return false;
}
if (!sceneData || !sceneData->node()) {
qWarning() << "OSGModelNode::acceptModelNode - no scene data";
return false;
}
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneData->node());
if (!mapNode) {
qWarning() << "OSGModelNode::acceptModelNode - scene data does not contain a map node";
return false;
}
// establish the coordinate system we wish to use:
// const osgEarth::SpatialReference* latLong = osgEarth::SpatialReference::get("wgs84");
osgEarth::Symbology::Style style;
// construct the symbology
osgEarth::Symbology::ModelSymbol *modelSymbol = style.getOrCreate<osgEarth::Symbology::ModelSymbol>();
modelSymbol->setModel(node);
// create ModelNode
modelNode = new osgEarth::Annotation::ModelNode(mapNode, style);
// add update callback
if (!nodeUpdateCallback.valid()) {
nodeUpdateCallback = new NodeUpdateCallback(this);
}
modelNode->addUpdateCallback(nodeUpdateCallback.get());
self->setNode(modelNode);
dirty = true;
return true;
}
bool acceptSceneData(OSGNode *node)
{
qDebug() << "OSGModelNode::acceptSceneData" << node;
if (sceneData == node) {
return false;
}
if (sceneData) {
disconnect(sceneData);
}
sceneData = node;
if (sceneData) {
// TODO find a better way
if (modelData && modelData->node()) {
acceptModelNode(modelData->node());
}
connect(sceneData, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onSceneNodeChanged(osg::Node *)));
}
return true;
}
// TODO model update gets jitter if camera is thrown (i.e animated)
void updateNode()
{
if (!dirty || !modelNode.valid()) {
return;
}
dirty = false;
osgEarth::GeoPoint geoPoint = osgQtQuick::toGeoPoint(position);
if (clampToTerrain) {
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneData->node());
if (mapNode) {
// get "size" of model
// TODO this should be done once only...
osg::ComputeBoundsVisitor cbv;
modelNode->accept(cbv);
const osg::BoundingBox & bbox = cbv.getBoundingBox();
offset = bbox.radius();
// clamp model to terrain if needed
intoTerrain = clampGeoPoint(geoPoint, offset, mapNode);
} else {
qWarning() << "OSGModelNode::updateNode - scene data does not contain a map node";
}
}
modelNode->setPosition(geoPoint);
modelNode->setLocalRotation(localRotation());
}
osg::Quat localRotation()
{
double roll = osg::DegreesToRadians(attitude.x());
double pitch = osg::DegreesToRadians(attitude.y());
double yaw = osg::DegreesToRadians(attitude.z());
osg::Quat q = osg::Quat(
roll, osg::Vec3d(0, 1, 0),
pitch, osg::Vec3d(1, 0, 0),
yaw, osg::Vec3d(0, 0, -1));
return q;
}
OSGModelNode *const self;
OSGNode *modelData;
OSGNode *sceneData;
osg::ref_ptr<osgEarth::Annotation::ModelNode> modelNode;
float offset;
bool clampToTerrain;
bool intoTerrain;
QVector3D attitude;
QVector3D position;
// handle attitude/position/etc independently
bool dirty;
osg::observer_ptr<NodeUpdateCallback> nodeUpdateCallback;
private slots:
void onModelNodeChanged(osg::Node *node)
{
qDebug() << "OSGModelNode::onModelNodeChanged" << node;
if (modelData) {
if (modelNode.valid()) {
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneData->node());
if (mapNode) {
mapNode->removeChild(modelNode);
}
if (nodeUpdateCallback.valid()) {
modelNode->removeUpdateCallback(nodeUpdateCallback.get());
}
}
if (node) {
acceptModelNode(node);
}
}
}
void onSceneNodeChanged(osg::Node *node)
{
qDebug() << "OSGModelNode::onSceneNodeChanged" << node;
// TODO needs to be improved...
if (modelData) {
if (modelNode.valid()) {
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneData->node());
if (mapNode) {
mapNode->removeChild(modelNode);
}
if (nodeUpdateCallback.valid()) {
modelNode->removeUpdateCallback(nodeUpdateCallback.get());
}
}
if (modelData->node()) {
acceptModelNode(modelData->node());
}
}
}
};
/* struct Hidden::NodeUpdateCallback */
void OSGModelNode::Hidden::NodeUpdateCallback::operator()(osg::Node *node, osg::NodeVisitor *nv)
{
h->updateNode();
}
OSGModelNode::OSGModelNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
qDebug() << "OSGModelNode::OSGModelNode";
}
OSGModelNode::~OSGModelNode()
{
qDebug() << "OSGModelNode::~OSGModelNode";
}
OSGNode *OSGModelNode::modelData()
{
return h->modelData;
}
void OSGModelNode::setModelData(OSGNode *node)
{
if (h->acceptModelData(node)) {
emit modelDataChanged(node);
}
}
OSGNode *OSGModelNode::sceneData()
{
return h->sceneData;
}
void OSGModelNode::setSceneData(OSGNode *node)
{
if (h->acceptSceneData(node)) {
emit sceneDataChanged(node);
}
}
bool OSGModelNode::clampToTerrain() const
{
return h->clampToTerrain;
}
void OSGModelNode::setClampToTerrain(bool arg)
{
if (h->clampToTerrain != arg) {
h->clampToTerrain = arg;
h->dirty = true;
emit clampToTerrainChanged(clampToTerrain());
}
}
bool OSGModelNode::intoTerrain() const
{
return h->intoTerrain;
}
QVector3D OSGModelNode::attitude() const
{
return h->attitude;
}
void OSGModelNode::setAttitude(QVector3D arg)
{
if (h->attitude != arg) {
h->attitude = arg;
h->dirty = true;
emit attitudeChanged(attitude());
}
}
QVector3D OSGModelNode::position() const
{
return h->position;
}
void OSGModelNode::setPosition(QVector3D arg)
{
if (h->position != arg) {
h->position = arg;
h->dirty = true;
emit positionChanged(position());
}
}
void OSGModelNode::attach(osgViewer::View *view)
{
// qDebug() << "OSGModelNode::attach " << view;
if (h->modelData) {
h->modelData->attach(view);
}
h->updateNode();
}
void OSGModelNode::detach(osgViewer::View *view)
{
// qDebug() << "OSGModelNode::detach " << view;
if (h->modelData) {
h->modelData->detach(view);
}
}
} // namespace osgQtQuick
#include "OSGModelNode.moc"

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 mask)
{
return (dirty && mask) != 0;
}
void setDirty(int mask)
{
// 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 |= mask;
// 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,17 +154,55 @@ 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);
}
}
void OSGNode::attach(osgViewer::View *view)
bool OSGNode::isDirty()
{
return h->isDirty(0xFFFFFFFF);
}
void OSGNode::detach(osgViewer::View *view)
bool OSGNode::isDirty(int mask)
{
return h->isDirty(mask);
}
void OSGNode::setDirty(int mask)
{
h->setDirty(mask);
}
void OSGNode::clearDirty()
{
h->clearDirty();
}
void OSGNode::attach(OSGNode *node, osgViewer::View *view)
{
if (!node) {
return;
}
node->attach(view);
}
void OSGNode::detach(OSGNode *node, osgViewer::View *view)
{
if (!node) {
return;
}
node->detach(view);
}
void OSGNode::update()
{}
void OSGNode::attach(osgViewer::View *view)
{}
void OSGNode::detach(osgViewer::View *view)
{}
} // namespace osgQtQuick
#include "OSGNode.moc"

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
@ -41,10 +53,12 @@ class View;
} // namespace osgViewer
namespace osgQtQuick {
class OSGQTQUICK_EXPORT OSGNode : public QObject {
Q_OBJECT
friend class OSGViewport;
friend class NodeUpdateCallback;
public:
explicit OSGNode(QObject *parent = 0);
virtual ~OSGNode();
@ -52,8 +66,19 @@ public:
osg::Node *node() const;
void setNode(osg::Node *node);
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
protected:
bool isDirty();
bool isDirty(int mask);
void setDirty(int mask);
void clearDirty();
void emitNodeChanged()
{
emit nodeChanged(node());
}
void attach(OSGNode *node, osgViewer::View *view);
void detach(OSGNode *node, osgViewer::View *view);
signals:
void nodeChanged(osg::Node *node) const;
@ -61,6 +86,11 @@ signals:
private:
struct Hidden;
Hidden *h;
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
virtual void update();
};
} // namespace osgQtQuick

View File

@ -40,13 +40,17 @@ namespace osgQtQuick {
struct OSGShapeNode::Hidden : public QObject {
Q_OBJECT
private:
OSGShapeNode * self;
public:
Hidden(OSGShapeNode *parent) : QObject(parent), self(parent), shapeType(ShapeType::Sphere) {}
ShapeType::Enum shapeType;
void realize()
Hidden(OSGShapeNode *node) : QObject(node), self(node), shapeType(ShapeType::Sphere)
{}
void updateNode()
{
qDebug() << "OSGShapeNode::realize";
osg::Node *node = NULL;
switch (shapeType) {
@ -63,40 +67,27 @@ public:
node = ShapeUtils::create3DAxis();
break;
}
// Add the node to the scene:
// Add the node to the scene
self->setNode(node);
}
bool acceptShapeType(ShapeType::Enum type)
{
if (shapeType == type) {
return false;
}
qDebug() << "OSGShapeNode::acceptShapeType" << type;
shapeType = type;
realize();
return true;
}
OSGShapeNode *self;
ShapeType::Enum shapeType;
};
/* class OSGShapeNode */
enum DirtyFlag { Type = 1 << 0 };
// TODO turn into generic shape node...
// see http://trac.openscenegraph.org/projects/osg//wiki/Support/Tutorials/TransformsAndStates
OSGShapeNode::OSGShapeNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
qDebug() << "OSGShapeNode::OSGShapeNode";
h->realize();
setShapeType(ShapeType::Sphere);
}
OSGShapeNode::~OSGShapeNode()
{
qDebug() << "OSGShapeNode::~OSGShapeNode";
// qDebug() << "OSGShapeNode::~OSGShapeNode";
delete h;
}
ShapeType::Enum OSGShapeNode::shapeType() const
@ -106,10 +97,28 @@ ShapeType::Enum OSGShapeNode::shapeType() const
void OSGShapeNode::setShapeType(ShapeType::Enum type)
{
if (h->acceptShapeType(type)) {
emit shapeTypeChanged(shapeType());
if (h->shapeType != type) {
h->shapeType = type;
setDirty(Type);
emit shapeTypeChanged(type);
}
}
void OSGShapeNode::update()
{
if (isDirty(Type)) {
h->updateNode();
}
}
void OSGShapeNode::attach(osgViewer::View *view)
{
update();
clearDirty();
}
void OSGShapeNode::detach(osgViewer::View *view)
{}
} // namespace osgQtQuick
#include "OSGShapeNode.moc"

View File

@ -55,6 +55,11 @@ signals:
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -42,9 +42,19 @@ namespace osgQtQuick {
struct OSGSkyNode::Hidden : public QObject {
Q_OBJECT
private:
OSGSkyNode * const self;
osg::ref_ptr<osgEarth::Util::SkyNode> skyNode;
public:
Hidden(OSGSkyNode *parent) : QObject(parent),
self(parent), sceneData(NULL), sunLightEnabled(true), minimumAmbientLight(0.03)
OSGNode *sceneNode;
bool sunLightEnabled;
QDateTime dateTime;
double minimumAmbientLight;
Hidden(OSGSkyNode *node) : QObject(node), self(node), sceneNode(NULL), sunLightEnabled(true), minimumAmbientLight(0.03)
{
dateTime = QDateTime::currentDateTime();
}
@ -55,59 +65,60 @@ public:
bool acceptSceneNode(OSGNode *node)
{
qDebug() << "OSGSkyNode::acceptSceneNode" << node;
if (sceneData == node) {
if (sceneNode == node) {
return false;
}
if (sceneData) {
disconnect(sceneData);
if (sceneNode) {
disconnect(sceneNode);
}
sceneData = node;
sceneNode = node;
if (sceneData) {
acceptNode(sceneData->node());
connect(sceneData, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onNodeChanged(osg::Node *)));
if (sceneNode) {
connect(sceneNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onSceneNodeChanged(osg::Node *)));
}
return true;
}
bool acceptNode(osg::Node *node)
void updateSkyNode()
{
qDebug() << "OSGSkyNode::acceptNode" << node;
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(node);
if (!sceneNode || !sceneNode->node()) {
qWarning() << "OSGSkyNode::acceptNode - scene node not valid";
self->setNode(NULL);
return;
}
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
if (!mapNode) {
qWarning() << "OSGSkyNode::acceptNode - scene data does not contain a map node";
return false;
qWarning() << "OSGSkyNode::acceptNode - scene node does not contain a map node";
self->setNode(NULL);
return;
}
if (!mapNode->getMap()->isGeocentric()) {
qWarning() << "OSGSkyNode::acceptNode - map node is not geocentric";
return false;
self->setNode(NULL);
return;
}
// create sky node
skyNode = createSimpleSky(mapNode);
// skyNode = createSilverLiningSky(mapNode);
if (!skyNode.valid()) {
skyNode = createSimpleSky(mapNode);
// skyNode = createSilverLiningSky(mapNode);
acceptSunLightEnabled(sunLightEnabled);
acceptDateTime(dateTime);
acceptMinimumAmbientLight(minimumAmbientLight);
// Ocean
// const osgEarth::Config & externals = mapNode->externalConfig();
// if (externals.hasChild("ocean")) {
// s_ocean = osgEarth::Util::OceanNode::create(osgEarth::Util::OceanOptions(externals.child("ocean")), mapNode);
// if (s_ocean) root->addChild(s_ocean);
// skyNode->setStarsVisible(false);
// Ocean
// const osgEarth::Config & externals = mapNode->externalConfig();
// if (externals.hasChild("ocean")) {
// s_ocean = osgEarth::Util::OceanNode::create(osgEarth::Util::OceanOptions(externals.child("ocean")), mapNode);
// if (s_ocean) root->addChild(s_ocean);
skyNode->addChild(node);
self->setNode(skyNode);
return true;
skyNode->addChild(sceneNode->node());
self->setNode(skyNode);
} else {
skyNode->removeChild(0, 1);
skyNode->addChild(sceneNode->node());
self->emitNodeChanged();
}
}
osgEarth::Util::SkyNode *createSimpleSky(osgEarth::MapNode *mapNode)
@ -131,65 +142,46 @@ public:
}
*/
bool acceptSunLightEnabled(bool enabled)
void updateSunLightEnabled()
{
// qDebug() << "OSGSkyNode::acceptSunLightEnabled" << enabled;
this->sunLightEnabled = enabled;
// TODO should be done in a node visitor...
if (skyNode) {
// skyNode->setLighting(sunLightEnabled ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
if (!skyNode.valid()) {
return;
}
return true;
// skyNode->setLighting(sunLightEnabled ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
}
bool acceptDateTime(QDateTime dateTime)
void updateDateTime()
{
qDebug() << "OSGSkyNode::acceptDateTime" << dateTime;
if (!skyNode.valid()) {
return;
}
if (!dateTime.isValid()) {
qWarning() << "OSGSkyNode::acceptDateTime - invalid date/time" << dateTime;
return false;
}
this->dateTime = dateTime;
// TODO should be done in a node visitor...
if (skyNode) {
QDate date = dateTime.date();
QTime time = dateTime.time();
double hours = time.hour() + (double)time.minute() / 60.0 + (double)time.second() / 3600.0;
skyNode->setDateTime(osgEarth::DateTime(date.year(), date.month(), date.day(), hours));
}
return true;
QDate date = dateTime.date();
QTime time = dateTime.time();
double hours = time.hour() + (double)time.minute() / 60.0 + (double)time.second() / 3600.0;
skyNode->setDateTime(osgEarth::DateTime(date.year(), date.month(), date.day(), hours));
}
bool acceptMinimumAmbientLight(double minimumAmbientLight)
void updateMinimumAmbientLight()
{
// qDebug() << "OSGSkyNode::acceptMinimumAmbientLight" << minimumAmbientLight;
this->minimumAmbientLight = minimumAmbientLight;
// TODO should be done in a node visitor...
if (skyNode) {
double d = minimumAmbientLight;
// skyNode->getSunLight()->setAmbient(osg::Vec4(d, d, d, 1.0f));
skyNode->setMinimumAmbient(osg::Vec4(d, d, d, 1.0f));
if (!skyNode.valid()) {
return;
}
return true;
double d = minimumAmbientLight;
// skyNode->getSunLight()->setAmbient(osg::Vec4(d, d, d, 1.0f));
skyNode->setMinimumAmbient(osg::Vec4(d, d, d, 1.0f));
}
void attachSkyNode(osgViewer::View *view)
{
if (!skyNode.valid()) {
qWarning() << "OSGSkyNode::attach - invalid sky node" << skyNode;
qWarning() << "OSGSkyNode::attachSkyNode - invalid sky node" << skyNode;
return;
}
skyNode->attach(view, 0);
skyNode->attach(view);
}
void detachSkyNode(osgViewer::View *view)
@ -197,43 +189,41 @@ public:
// TODO find a way to detach the skyNode (?)
}
OSGSkyNode *const self;
OSGNode *sceneData;
osg::ref_ptr<osgEarth::Util::SkyNode> skyNode;
bool sunLightEnabled;
QDateTime dateTime;
double minimumAmbientLight;
private slots:
void onNodeChanged(osg::Node *node)
void onSceneNodeChanged(osg::Node *node)
{
qDebug() << "OSGSkyNode::onNodeChanged" << node;
acceptNode(node);
qDebug() << "OSGSkyNode::onSceneNodeChanged" << node;
updateSkyNode();
}
};
/* class OSGSkyNode */
enum DirtyFlag { Child = 1 << 0, DateTime = 1 << 1, Light = 1 << 2 };
OSGSkyNode::OSGSkyNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
qDebug() << "OSGSkyNode::OSGSkyNode";
setSunLightEnabled(true);
setMinimumAmbientLight(0.03);
}
OSGSkyNode::~OSGSkyNode()
{
qDebug() << "OSGSkyNode::~OSGSkyNode";
// qDebug() << "OSGSkyNode::~OSGSkyNode";
delete h;
}
OSGNode *OSGSkyNode::sceneData()
OSGNode *OSGSkyNode::sceneNode()
{
return h->sceneData;
return h->sceneNode;
}
void OSGSkyNode::setSceneData(OSGNode *node)
void OSGSkyNode::setSceneNode(OSGNode *node)
{
if (h->acceptSceneNode(node)) {
emit sceneDataChanged(node);
setDirty(Child);
emit sceneNodeChanged(node);
}
}
@ -242,10 +232,12 @@ bool OSGSkyNode::sunLightEnabled()
return h->sunLightEnabled;
}
void OSGSkyNode::setSunLightEnabled(bool arg)
void OSGSkyNode::setSunLightEnabled(bool enabled)
{
if (h->acceptSunLightEnabled(arg)) {
emit sunLightEnabledChanged(sunLightEnabled());
if (h->sunLightEnabled != enabled) {
h->sunLightEnabled = enabled;
setDirty(Light);
emit sunLightEnabledChanged(enabled);
}
}
@ -254,10 +246,12 @@ QDateTime OSGSkyNode::dateTime()
return h->dateTime;
}
void OSGSkyNode::setDateTime(QDateTime arg)
void OSGSkyNode::setDateTime(QDateTime dateTime)
{
if (h->acceptDateTime(arg)) {
emit dateTimeChanged(dateTime());
if (h->dateTime != dateTime) {
h->dateTime = dateTime;
setDirty(DateTime);
emit dateTimeChanged(dateTime);
}
}
@ -266,29 +260,44 @@ double OSGSkyNode::minimumAmbientLight()
return h->minimumAmbientLight;
}
void OSGSkyNode::setMinimumAmbientLight(double arg)
void OSGSkyNode::setMinimumAmbientLight(double ambient)
{
if (h->acceptMinimumAmbientLight(arg)) {
emit minimumAmbientLightChanged(minimumAmbientLight());
if (h->minimumAmbientLight != ambient) {
h->minimumAmbientLight = ambient;
setDirty(Light);
emit minimumAmbientLightChanged(ambient);
}
}
void OSGSkyNode::update()
{
if (isDirty(Child)) {
h->updateSkyNode();
}
if (isDirty(Light)) {
h->updateSunLightEnabled();
h->updateMinimumAmbientLight();
}
if (isDirty(DateTime)) {
h->updateDateTime();
}
}
void OSGSkyNode::attach(osgViewer::View *view)
{
// qDebug() << "OSGSkyNode::attach " << view;
if (h->sceneData) {
h->sceneData->attach(view);
}
OSGNode::attach(h->sceneNode, view);
h->attachSkyNode(view);
update();
clearDirty();
}
void OSGSkyNode::detach(osgViewer::View *view)
{
// qDebug() << "OSGSkyNode::detach " << view;
h->detachSkyNode(view);
if (h->sceneData) {
h->sceneData->detach(view);
}
OSGNode::detach(h->sceneNode, view);
}
} // namespace osgQtQuick

View File

@ -44,7 +44,8 @@ QT_END_NAMESPACE
namespace osgQtQuick {
class OSGQTQUICK_EXPORT OSGSkyNode : public OSGNode {
Q_OBJECT Q_PROPERTY(osgQtQuick::OSGNode *sceneData READ sceneData WRITE setSceneData NOTIFY sceneDataChanged)
// TODO rename to sceneNode
Q_OBJECT Q_PROPERTY(osgQtQuick::OSGNode *sceneData READ sceneNode WRITE setSceneNode NOTIFY sceneNodeChanged)
Q_PROPERTY(bool sunLightEnabled READ sunLightEnabled WRITE setSunLightEnabled NOTIFY sunLightEnabledChanged)
Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY dateTimeChanged)
@ -54,8 +55,8 @@ public:
OSGSkyNode(QObject *parent = 0);
virtual ~OSGSkyNode();
OSGNode *sceneData();
void setSceneData(OSGNode *node);
OSGNode *sceneNode();
void setSceneNode(OSGNode *node);
bool sunLightEnabled();
void setSunLightEnabled(bool arg);
@ -66,11 +67,8 @@ public:
double minimumAmbientLight();
void setMinimumAmbientLight(double arg);
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
signals:
void sceneDataChanged(OSGNode *node);
void sceneNodeChanged(OSGNode *node);
void sunLightEnabledChanged(bool arg);
void dateTimeChanged(QDateTime arg);
@ -79,6 +77,11 @@ signals:
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -37,36 +37,61 @@
#include <QColor>
namespace osgQtQuick {
struct OSGTextNode::Hidden {
public:
struct OSGTextNode::Hidden : public QObject {
Q_OBJECT
private:
OSGTextNode * const self;
osg::ref_ptr<osgText::Text> text;
public:
QString textString;
QColor color;
Hidden(OSGTextNode *node) : QObject(node), self(node)
{
osg::ref_ptr<osgText::Font> textFont = createFont(QFont("Times"));
text = createText(osg::Vec3(-100, 20, 0), "Hello World", 20.0f,
textFont.get());
osg::ref_ptr<osg::Geode> textGeode = new osg::Geode();
textGeode->addDrawable(text.get());
#if 0
text->setAutoRotateToScreen(true);
self->setNode(textGeode.get());
#else
osg::Camera *camera = createHUDCamera(-100, 100, -100, 100);
camera->addChild(textGeode.get());
camera->getOrCreateStateSet()->setMode(
GL_LIGHTING, osg::StateAttribute::OFF);
self->setNode(camera);
#endif
}
void updateText()
{
text->setText(textString.toStdString(), osgText::String::ENCODING_UTF8);
}
void updateColor()
{
osg::Vec4 osgColor(
color.redF(),
color.greenF(),
color.blueF(),
color.alphaF());
text->setColor(osgColor);
}
};
OSGTextNode::OSGTextNode(QObject *parent) :
osgQtQuick::OSGNode(parent),
h(new Hidden)
{
osg::ref_ptr<osgText::Font> textFont = createFont(QFont("Times"));
/* class OSGTextNode */
h->text = createText(osg::Vec3(-100, 20, 0),
"The osgQtQuick :-)\n"
"И даже по русски!",
20.0f,
textFont.get());
osg::ref_ptr<osg::Geode> textGeode = new osg::Geode();
h->text->setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
textGeode->addDrawable(h->text.get());
#if 0
h->text->setAutoRotateToScreen(true);
setNode(textGeode.get());
#else
osg::Camera *camera = createHUDCamera(-100, 100, -100, 100);
camera->addChild(textGeode.get());
camera->getOrCreateStateSet()->setMode(
GL_LIGHTING, osg::StateAttribute::OFF);
setNode(camera);
#endif
}
enum DirtyFlag { Text = 1 << 0, Color = 1 << 1 };
OSGTextNode::OSGTextNode(QObject *node) : OSGNode(node), h(new Hidden(this))
{}
OSGTextNode::~OSGTextNode()
{
@ -75,42 +100,50 @@ OSGTextNode::~OSGTextNode()
QString OSGTextNode::text() const
{
return QString::fromUtf8(
h->text->getText().createUTF8EncodedString().data());
return h->textString;
}
void OSGTextNode::setText(const QString &text)
{
std::string oldText = h->text->getText().createUTF8EncodedString();
if (text.toStdString() != oldText) {
h->text->setText(text.toStdString(), osgText::String::ENCODING_UTF8);
if (h->textString != text) {
h->textString != text;
setDirty(Text);
emit textChanged(text);
}
}
QColor OSGTextNode::color() const
{
const osg::Vec4 osgColor = h->text->getColor();
return QColor::fromRgbF(
osgColor.r(),
osgColor.g(),
osgColor.b(),
osgColor.a());
return h->color;
}
void OSGTextNode::setColor(const QColor &color)
{
osg::Vec4 osgColor(
color.redF(),
color.greenF(),
color.blueF(),
color.alphaF());
if (h->text->getColor() != osgColor) {
h->text->setColor(osgColor);
if (h->color != color) {
h->color != color;
setDirty(Color);
emit colorChanged(color);
}
}
void OSGTextNode::update()
{
if (isDirty(Text)) {
h->updateText();
}
if (isDirty(Color)) {
h->updateColor();
}
}
void OSGTextNode::attach(osgViewer::View *view)
{
update();
clearDirty();
}
void OSGTextNode::detach(osgViewer::View *view)
{}
} // namespace osgQtQuick
#include "OSGTextNode.moc"

View File

@ -52,11 +52,14 @@ signals:
void textChanged(const QString &text);
void colorChanged(const QColor &color);
public slots:
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -37,92 +37,78 @@ namespace osgQtQuick {
struct OSGTransformNode::Hidden : public QObject {
Q_OBJECT
struct NodeUpdateCallback : public osg::NodeCallback {
public:
NodeUpdateCallback(Hidden *h) : h(h) {}
private:
OSGTransformNode * const self;
void operator()(osg::Node *node, osg::NodeVisitor *nv);
mutable Hidden *h;
};
friend class NodeUpdateCallback;
osg::ref_ptr<osg::PositionAttitudeTransform> transform;
public:
OSGNode *childNode;
Hidden(OSGTransformNode *parent) : QObject(parent), self(parent), modelData(NULL), dirty(false)
{}
QVector3D scale;
QVector3D attitude;
QVector3D position;
~Hidden()
{}
bool acceptModelData(OSGNode *node)
Hidden(OSGTransformNode *node) : QObject(node), self(node), childNode(NULL)
{
qDebug() << "OSGTransformNode::acceptModelData" << node;
if (modelData == node) {
return false;
}
if (modelData) {
disconnect(modelData);
}
modelData = node;
if (modelData) {
acceptNode(modelData->node());
connect(modelData, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onNodeChanged(osg::Node *)));
}
return true;
}
bool acceptNode(osg::Node *node)
{
qDebug() << "OSGTransformNode::acceptNode" << node;
if (!node) {
qWarning() << "OSGTransformNode::acceptNode - node is null";
return false;
}
osg::Transform *transform = getOrCreateTransform();
transform->addChild(node);
self->setNode(transform);
dirty = true;
return true;
}
osg::Transform *getOrCreateTransform()
{
if (transform.valid()) {
return transform.get();
}
transform = new osg::PositionAttitudeTransform();
transform->addUpdateCallback(new NodeUpdateCallback(this));
return transform.get();
self->setNode(transform);
}
void updateNode()
bool acceptChildNode(OSGNode *node)
{
if (!dirty || !transform.valid()) {
return;
qDebug() << "OSGTransformNode::acceptChildNode" << node;
if (childNode == node) {
return false;
}
dirty = false;
// scale
if (childNode) {
disconnect(childNode);
}
childNode = node;
if (childNode) {
connect(childNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onChildNodeChanged(osg::Node *)));
}
return true;
}
void updateTransformNode()
{
bool updated = false;
if (transform->getNumChildren() == 0) {
if (childNode && childNode->node()) {
updated |= transform->addChild(childNode->node());
}
} else {
if (childNode && childNode->node()) {
if (transform->getChild(0) != childNode->node()) {
updated |= transform->removeChild(0, 1);
updated |= transform->addChild(childNode->node());
}
} else {
updated |= transform->removeChild(0, 1);
}
}
// if (updated) {
self->emitNodeChanged();
// }
}
void updateScale()
{
if ((scale.x() != 0.0) || (scale.y() != 0.0) || (scale.z() != 0.0)) {
transform->setScale(osg::Vec3d(scale.x(), scale.y(), scale.z()));
// transform->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
transform->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
}
}
// attitude
void updateAttitude()
{
double roll = osg::DegreesToRadians(attitude.x());
double pitch = osg::DegreesToRadians(attitude.y());
double yaw = osg::DegreesToRadians(attitude.z());
@ -130,39 +116,29 @@ public:
roll, osg::Vec3d(0, 1, 0),
pitch, osg::Vec3d(1, 0, 0),
yaw, osg::Vec3d(0, 0, -1));
transform->setAttitude(q);
// position
transform->setPosition(osg::Vec3d(position.x(), position.y(), position.z()));
}
OSGTransformNode *const self;
OSGNode *modelData;
osg::ref_ptr<osg::PositionAttitudeTransform> transform;
bool dirty;
QVector3D scale;
QVector3D attitude;
QVector3D position;
void updatePosition()
{
transform->setPosition(osg::Vec3d(position.x(), position.y(), position.z()));
}
private slots:
void onNodeChanged(osg::Node *node)
void onChildNodeChanged(osg::Node *node)
{
qDebug() << "OSGTransformNode::onNodeChanged" << node;
acceptNode(node);
qDebug() << "OSGTransformNode::onChildNodeChanged" << node;
updateTransformNode();
}
};
/* struct Hidden::NodeUpdateCallback */
/* class OSGTransformNode */
void OSGTransformNode::Hidden::NodeUpdateCallback::operator()(osg::Node *node, osg::NodeVisitor *nv)
{
h->updateNode();
}
enum DirtyFlag { Child = 1 << 0, Scale = 1 << 1, Position = 1 << 2, Attitude = 1 << 3 };
OSGTransformNode::OSGTransformNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
@ -171,18 +147,20 @@ OSGTransformNode::OSGTransformNode(QObject *parent) : OSGNode(parent), h(new Hid
OSGTransformNode::~OSGTransformNode()
{
qDebug() << "OSGTransformNode::~OSGTransformNode";
// qDebug() << "OSGTransformNode::~OSGTransformNode";
delete h;
}
OSGNode *OSGTransformNode::modelData()
OSGNode *OSGTransformNode::childNode()
{
return h->modelData;
return h->childNode;
}
void OSGTransformNode::setModelData(OSGNode *node)
void OSGTransformNode::setChildNode(OSGNode *node)
{
if (h->acceptModelData(node)) {
emit modelDataChanged(node);
if (h->acceptChildNode(node)) {
setDirty(Child);
emit childNodeChanged(node);
}
}
@ -195,7 +173,7 @@ void OSGTransformNode::setScale(QVector3D arg)
{
if (h->scale != arg) {
h->scale = arg;
h->dirty = true;
setDirty(Scale);
emit scaleChanged(scale());
}
}
@ -209,7 +187,7 @@ void OSGTransformNode::setAttitude(QVector3D arg)
{
if (h->attitude != arg) {
h->attitude = arg;
h->dirty = true;
setDirty(Attitude);
emit attitudeChanged(attitude());
}
}
@ -223,26 +201,38 @@ void OSGTransformNode::setPosition(QVector3D arg)
{
if (h->position != arg) {
h->position = arg;
h->dirty = true;
setDirty(Position);
emit positionChanged(position());
}
}
void OSGTransformNode::update()
{
if (isDirty(Child)) {
h->updateTransformNode();
}
if (isDirty(Scale)) {
h->updateScale();
}
if (isDirty(Attitude)) {
h->updateAttitude();
}
if (isDirty(Position)) {
h->updatePosition();
}
}
void OSGTransformNode::attach(osgViewer::View *view)
{
// qDebug() << "OSGTransformNode::attach " << view;
if (h->modelData) {
h->modelData->attach(view);
}
h->updateNode();
OSGNode::attach(h->childNode, view);
update();
clearDirty();
}
void OSGTransformNode::detach(osgViewer::View *view)
{
// qDebug() << "OSGTransformNode::detach " << view;
if (h->modelData) {
h->modelData->detach(view);
}
OSGNode::detach(h->childNode, view);
}
} // namespace osgQtQuick

View File

@ -37,8 +37,8 @@
namespace osgQtQuick {
class OSGQTQUICK_EXPORT OSGTransformNode : public OSGNode {
Q_OBJECT
// TODO rename to parentNode and modelNode
Q_PROPERTY(osgQtQuick::OSGNode *modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
// TODO rename to childNode
Q_PROPERTY(osgQtQuick::OSGNode *modelData READ childNode WRITE setChildNode NOTIFY childNodeChanged)
Q_PROPERTY(QVector3D scale READ scale WRITE setScale NOTIFY scaleChanged)
Q_PROPERTY(QVector3D attitude READ attitude WRITE setAttitude NOTIFY attitudeChanged)
@ -48,8 +48,8 @@ public:
OSGTransformNode(QObject *parent = 0);
virtual ~OSGTransformNode();
OSGNode *modelData();
void setModelData(OSGNode *node);
OSGNode *childNode();
void setChildNode(OSGNode *node);
QVector3D scale() const;
void setScale(QVector3D arg);
@ -60,11 +60,8 @@ public:
QVector3D position() const;
void setPosition(QVector3D arg);
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
signals:
void modelDataChanged(OSGNode *node);
void childNodeChanged(OSGNode *node);
void scaleChanged(QVector3D arg);
void attitudeChanged(QVector3D arg);
@ -73,6 +70,11 @@ signals:
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

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()
@ -187,7 +187,7 @@ public:
qDebug() << "OSGViewport::attach - found map node" << mapNode;
// remove light to prevent unnecessary state changes in SceneView
// scene will get light from sky
// scene will get light from sky (works only with latest > 2.7)
// view->setLightingMode(osg::View::NO_LIGHT);
}
#endif
@ -354,6 +354,10 @@ public:
// setup graphics context and camera
osg::GraphicsContext *gc = createGraphicsContext();
// TODO expose as Qml properties
view->setLightingMode(osgViewer::View::SKY_LIGHT);
view->getLight()->setAmbient(osg::Vec4(0.6f, 0.6f, 0.6f, 1.0f));
osg::Camera *camera = view->getCamera();
camera->setGraphicsContext(gc);
camera->setViewport(0, 0, gc->getTraits()->width, gc->getTraits()->height);
@ -459,7 +463,7 @@ public:
ViewportRenderer(OSGViewport::Hidden *h) : h(h)
{
qDebug() << "ViewportRenderer::ViewportRenderer";
osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "ViewportRenderer::ViewportRenderer");
// osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "ViewportRenderer::ViewportRenderer");
h->initializeResources();
@ -470,7 +474,7 @@ public:
~ViewportRenderer()
{
qDebug() << "ViewportRenderer::~ViewportRenderer";
osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "ViewportRenderer::~ViewportRenderer");
// osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "ViewportRenderer::~ViewportRenderer");
}
// This function is the only place when it is safe for the renderer and the item to read and write each others members.
@ -489,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();
@ -573,6 +585,7 @@ OSGViewport::OSGViewport(QQuickItem *parent) : QQuickFramebufferObject(parent),
OSGViewport::~OSGViewport()
{
qDebug() << "OSGViewport::~OSGViewport";
delete h;
}
UpdateMode::Enum OSGViewport::updateMode() const
@ -631,7 +644,7 @@ void OSGViewport::setCamera(OSGCamera *camera)
QQuickFramebufferObject::Renderer *OSGViewport::createRenderer() const
{
qDebug() << "OSGViewport::createRenderer";
osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "createRenderer");
// osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "createRenderer");
return new ViewportRenderer(h);
}

View File

@ -72,11 +72,8 @@ public:
OSGCamera *camera();
void setCamera(OSGCamera *camera);
virtual Renderer *createRenderer() const;
virtual void releaseResources();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
Renderer *createRenderer() const;
void releaseResources();
signals:
void updateModeChanged(UpdateMode::Enum mode);
@ -97,6 +94,9 @@ protected:
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
void attach(osgViewer::View *view);
void detach(osgViewer::View *view);
private:
struct Hidden;
Hidden *h;

View File

@ -70,11 +70,11 @@ SOURCES += \
osgQtQuick/OSGViewport.cpp
osgearth:HEADERS += \
osgQtQuick/OSGModelNode.hpp \
osgQtQuick/OSGSkyNode.hpp
osgQtQuick/OSGSkyNode.hpp \
osgQtQuick/OSGGeoTransformNode.hpp
osgearth:SOURCES += \
osgQtQuick/OSGModelNode.cpp \
osgQtQuick/OSGSkyNode.cpp
osgQtQuick/OSGSkyNode.cpp \
osgQtQuick/OSGGeoTransformNode.cpp
copy_osg:include(copydata.pro)

View File

@ -34,9 +34,7 @@
#include "osgQtQuick/OSGTransformNode.hpp"
#include "osgQtQuick/OSGShapeNode.hpp"
#include "osgQtQuick/OSGTextNode.hpp"
#include "osgQtQuick/OSGModelNode.hpp"
#include "osgQtQuick/OSGBackgroundNode.hpp"
#include "osgQtQuick/OSGSkyNode.hpp"
#include "osgQtQuick/OSGCamera.hpp"
#include "osgQtQuick/OSGViewport.hpp"
@ -60,6 +58,9 @@
#endif // USE_OSG_QT
#ifdef USE_OSGEARTH
#include "osgQtQuick/OSGSkyNode.hpp"
#include "osgQtQuick/OSGGeoTransformNode.hpp"
#include <osgEarth/Capabilities>
#include <osgEarth/MapNode>
#include <osgEarth/SpatialReference>
@ -440,14 +441,18 @@ QString getUsageString(osgViewer::CompositeViewer *viewer)
}
#ifdef USE_OSGEARTH
osgEarth::GeoPoint toGeoPoint(const QVector3D &position)
osgEarth::GeoPoint toGeoPoint(const osgEarth::SpatialReference *srs, const QVector3D &position)
{
osgEarth::GeoPoint geoPoint(osgEarth::SpatialReference::get("wgs84"),
position.x(), position.y(), position.z(), osgEarth::ALTMODE_ABSOLUTE);
osgEarth::GeoPoint geoPoint(srs, position.x(), position.y(), position.z(), osgEarth::ALTMODE_ABSOLUTE);
return geoPoint;
}
osgEarth::GeoPoint toGeoPoint(const QVector3D &position)
{
return toGeoPoint(osgEarth::SpatialReference::get("wgs84"), position);
}
bool clampGeoPoint(osgEarth::GeoPoint &geoPoint, float offset, osgEarth::MapNode *mapNode)
{
if (!mapNode) {
@ -542,8 +547,8 @@ void registerTypes()
qmlRegisterType<osgQtQuick::TrackerMode>("OsgQtQuick", maj, min, "TrackerMode");
#ifdef USE_OSGEARTH
qmlRegisterType<osgQtQuick::OSGModelNode>("OsgQtQuick", maj, min, "OSGModelNode");
qmlRegisterType<osgQtQuick::OSGSkyNode>("OsgQtQuick", maj, min, "OSGSkyNode");
qmlRegisterType<osgQtQuick::OSGGeoTransformNode>("OsgQtQuick", maj, min, "OSGGeoTransformNode");
#endif // USE_OSGEARTH
}
} // namespace osgQtQuick

View File

@ -62,6 +62,7 @@ namespace osgEarth {
class Capabilities;
class GeoPoint;
class MapNode;
class SpatialReference;
} // namespace osgEarth
#endif
@ -145,6 +146,7 @@ QString getUsageString(osgViewer::CompositeViewer *viewer);
#ifdef USE_OSGEARTH
osgEarth::GeoPoint toGeoPoint(const QVector3D &position);
osgEarth::GeoPoint toGeoPoint(const osgEarth::SpatialReference *srs, const QVector3D &position);
bool clampGeoPoint(osgEarth::GeoPoint &geoPoint, float offset, osgEarth::MapNode *mapNode);
void capabilitiesInfo(const osgEarth::Capabilities & caps);
#endif

View File

@ -278,6 +278,15 @@ void PfdQmlContext::loadConfiguration(PfdQmlGadgetConfiguration *config)
setBackgroundImageFile(config->backgroundImageFile());
}
void PfdQmlContext::saveState(QSettings *settings)
{
}
void PfdQmlContext::restoreState(QSettings *settings)
{
}
void PfdQmlContext::apply(QQmlContext *context)
{
QStringList objectsToExport;
@ -329,5 +338,5 @@ void PfdQmlContext::apply(QQmlContext *context)
}
// to expose settings values
context->setContextProperty("qmlWidget", this);
context->setContextProperty("pfdContext", this);
}

View File

@ -32,6 +32,7 @@
#include "pfdqmlgadgetconfiguration.h"
class QQmlContext;
class QSettings;
class PfdQmlContext : public QObject {
Q_OBJECT Q_PROPERTY(QString speedUnit READ speedUnit WRITE setSpeedUnit NOTIFY speedUnitChanged)
@ -94,6 +95,9 @@ public:
Q_INVOKABLE void resetConsumedEnergy();
void loadConfiguration(PfdQmlGadgetConfiguration *config);
void saveState(QSettings *);
void restoreState(QSettings *);
void apply(QQmlContext *context);
signals:

View File

@ -51,3 +51,13 @@ void PfdQmlGadget::loadConfiguration(IUAVGadgetConfiguration *config)
m_qmlGadgetWidget->loadConfiguration(m);
}
void PfdQmlGadget::saveState(QSettings *settings)
{
m_qmlGadgetWidget->saveState(settings);
}
void PfdQmlGadget::restoreState(QSettings *settings)
{
m_qmlGadgetWidget->restoreState(settings);
}

View File

@ -46,6 +46,8 @@ public:
QWidget *widget();
void loadConfiguration(IUAVGadgetConfiguration *config);
void saveState(QSettings *);
void restoreState(QSettings *);
private:
PfdQmlGadgetWidget *m_qmlGadgetWidget;

View File

@ -93,6 +93,16 @@ void PfdQmlGadgetWidget::loadConfiguration(PfdQmlGadgetConfiguration *config)
setQmlFile(config->qmlFile());
}
void PfdQmlGadgetWidget::saveState(QSettings *settings)
{
m_pfdQmlContext->saveState(settings);
}
void PfdQmlGadgetWidget::restoreState(QSettings *settings)
{
m_pfdQmlContext->restoreState(settings);
}
void PfdQmlGadgetWidget::setQmlFile(QString fn)
{
qDebug() << "PfdQmlGadgetWidget::setQmlFile" << fn;
@ -117,6 +127,7 @@ void PfdQmlGadgetWidget::setQmlFile(QString fn)
QUrl url = QUrl::fromLocalFile(fn);
engine()->setBaseUrl(url);
setSource(url);
}

View File

@ -34,6 +34,7 @@
#include <QWidget>
class QQmlEngine;
class QSettings;
class QuickWidgetProxy;
class PfdQmlContext;
@ -45,6 +46,8 @@ public:
virtual ~PfdQmlGadgetWidget();
void loadConfiguration(PfdQmlGadgetConfiguration *config);
void saveState(QSettings *);
void restoreState(QSettings *);
private:
void setQmlFile(QString);

View File

@ -35,12 +35,12 @@ Item {
id: skyNode
sceneData: terrainNode
dateTime: Utils.getDateTime()
minimumAmbientLight: qmlWidget.minimumAmbientLight
minimumAmbientLight: pfdContext.minimumAmbientLight
}
OSGFileNode {
id: terrainNode
source: qmlWidget.terrainFile
source: pfdContext.terrainFile
async: false
}

View File

@ -23,6 +23,6 @@ Item {
Loader {
anchors.fill: parent
focus: true
source: qmlWidget.terrainEnabled ? "model/ModelTerrainView.qml" : "model/ModelView.qml"
source: pfdContext.terrainEnabled ? "model/ModelTerrainView.qml" : "model/ModelView.qml"
}
}

View File

@ -61,7 +61,7 @@ Rectangle {
id: worldLoader
anchors.fill: parent
focus: true
source: qmlWidget.terrainEnabled ? "pfd/PfdTerrainView.qml" : "pfd/PfdWorldView.qml"
source: pfdContext.terrainEnabled ? "pfd/PfdTerrainView.qml" : "pfd/PfdWorldView.qml"
}
Pfd.HorizontCenter {
@ -103,7 +103,7 @@ Rectangle {
Pfd.VsiScale {
anchors.fill: parent
sceneSize: sceneItem.viewportSize
visible: qmlWidget.altitudeUnit != 0
visible: pfdContext.altitudeUnit != 0
}
Pfd.Info {

View File

@ -24,11 +24,11 @@
// Get date
function getDateTime() {
switch(qmlWidget.timeMode) {
switch(pfdContext.timeMode) {
case TimeMode.Local:
return new Date();
case TimeMode.Predefined:
return qmlWidget.dateTime;
return pfdContext.dateTime;
}
}

View File

@ -35,7 +35,7 @@ OSGViewport {
id: skyNode
sceneData: sceneGroup
dateTime: Utils.getDateTime()
minimumAmbientLight: qmlWidget.minimumAmbientLight
minimumAmbientLight: pfdContext.minimumAmbientLight
}
OSGGroup {
@ -45,17 +45,18 @@ OSGViewport {
OSGFileNode {
id: terrainNode
source: qmlWidget.terrainFile
source: pfdContext.terrainFile
async: false
}
OSGModelNode {
OSGGeoTransformNode {
id: modelNode
clampToTerrain: true
modelData: modelTransformNode
sceneData: terrainNode
attitude: UAV.attitude()
clampToTerrain: true
position: UAV.position()
}
@ -64,11 +65,16 @@ OSGViewport {
modelData: modelFileNode
// model dimensions are in mm, scale to meters
scale: Qt.vector3d(0.001, 0.001, 0.001)
attitude: UAV.attitude()
}
OSGFileNode {
id: modelFileNode
source: qmlWidget.modelFile
// use ShaderGen pseudoloader to generate the shaders expected by osgEarth
// see http://docs.osgearth.org/en/latest/faq.html#i-added-a-node-but-it-has-no-texture-lighting-etc-in-osgearth-why
source: pfdContext.modelFile + ".osgearth_shadergen"
async: false
optimizeMode: OptimizeMode.OptimizeAndCheck
}
@ -79,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

@ -41,7 +41,7 @@ Item {
OSGBackgroundNode {
id: backgroundNode
imageFile: qmlWidget.backgroundImageFile
imageFile: pfdContext.backgroundImageFile
}
OSGTransformNode {
@ -52,7 +52,7 @@ Item {
OSGFileNode {
id: fileNode
source: qmlWidget.modelFile
source: pfdContext.modelFile
async: false
optimizeMode: OptimizeMode.OptimizeAndCheck
}
@ -60,7 +60,7 @@ Item {
OSGCamera {
id: camera
fieldOfView: 90
node: transformNode
sceneNode: transformNode
}
}

View File

@ -26,7 +26,7 @@ Item {
id: sceneItem
property variant sceneSize
property real altitude : -qmlWidget.altitudeFactor * UAV.positionStateDown()
property real altitude : -pfdContext.altitudeFactor * UAV.positionStateDown()
SvgElementImage {
id: altitude_window
@ -34,7 +34,7 @@ Item {
sceneSize: sceneItem.sceneSize
clip: true
visible: qmlWidget.altitudeUnit != 0
visible: pfdContext.altitudeUnit != 0
property variant scaledBounds: svgRenderer.scaledElementBounds("pfd/pfd.svg", "altitude-window")
@ -98,7 +98,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -altitude_scale.height / 10 *
(UAV.positionStateDown() - UAV.pathDesiredEndDown()) * qmlWidget.altitudeFactor
(UAV.positionStateDown() - UAV.pathDesiredEndDown()) * pfdContext.altitudeFactor
}
}
@ -106,7 +106,7 @@ Item {
id: altitude_box
clip: true
visible: qmlWidget.altitudeUnit != 0
visible: pfdContext.altitudeUnit != 0
elementName: "altitude-box"
sceneSize: sceneItem.sceneSize
@ -136,7 +136,7 @@ Item {
elementName: "altitude-unit-box"
sceneSize: sceneItem.sceneSize
visible: qmlWidget.altitudeUnit != 0
visible: pfdContext.altitudeUnit != 0
anchors.top: altitude_window.bottom
anchors.right: altitude_window.right
@ -145,7 +145,7 @@ Item {
Text {
id: altitude_unit_text
text: qmlWidget.altitudeUnit
text: pfdContext.altitudeUnit
color: "cyan"
font {
family: pt_bold.name

View File

@ -62,7 +62,7 @@ Item {
sceneSize: info.sceneSize
elementName: "info-bg"
width: parent.width
opacity: qmlWidget.terrainEnabled ? 0.3 : 1
opacity: pfdContext.terrainEnabled ? 0.3 : 1
}
//
@ -374,7 +374,7 @@ Item {
id: reset_consumed_energy_mouseArea;
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor;
onClicked: qmlWidget.resetConsumedEnergy();
onClicked: pfdContext.resetConsumedEnergy();
}
// Alarm based on estimatedFlightTime < 120s orange, < 60s red
@ -452,7 +452,7 @@ Item {
x: Math.floor(scaledBounds.x * sceneItem.width)
y: Math.floor(scaledBounds.y * sceneItem.height)
opacity: qmlWidget.terrainEnabled ? 0.6 : 1
opacity: pfdContext.terrainEnabled ? 0.6 : 1
states: State {
name: "fading"

View File

@ -541,7 +541,7 @@ Item {
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor;
visible: display_bat == true ? 1 : 0
onClicked: qmlWidget.resetConsumedEnergy();
onClicked: pfdContext.resetConsumedEnergy();
}
// Alarm based on estimatedFlightTime < 120s orange, < 60s red
@ -598,7 +598,7 @@ Item {
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor;
visible: display_bat == true ? 1 : 0
onClicked: qmlWidget.resetConsumedEnergy();
onClicked: pfdContext.resetConsumedEnergy();
}
// Alarm based on estimatedFlightTime < 120s orange, < 60s red

View File

@ -45,19 +45,19 @@ OSGViewport {
id: skyNode
sceneData: terrainNode
dateTime: Utils.getDateTime()
minimumAmbientLight: qmlWidget.minimumAmbientLight
minimumAmbientLight: pfdContext.minimumAmbientLight
}
OSGFileNode {
id: terrainNode
source: qmlWidget.terrainFile
source: pfdContext.terrainFile
async: false
}
OSGCamera {
id: camera
fieldOfView: 100
sceneData: terrainNode
sceneNode: terrainNode
logarithmicDepthBuffer: true
clampToTerrain: true
manipulatorMode: ManipulatorMode.User

View File

@ -24,7 +24,7 @@ import "../uav.js" as UAV
Item {
id: sceneItem
property variant sceneSize
property real groundSpeed : qmlWidget.speedFactor * UAV.currentVelocity()
property real groundSpeed : pfdContext.speedFactor * UAV.currentVelocity()
SvgElementImage {
id: speed_window
@ -32,7 +32,7 @@ Item {
sceneSize: sceneItem.sceneSize
clip: true
visible: qmlWidget.speedUnit != 0
visible: pfdContext.speedUnit != 0
x: Math.floor(scaledBounds.x * sceneItem.width)
y: Math.floor(scaledBounds.y * sceneItem.height)
@ -88,7 +88,7 @@ Item {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: speed_scale.height / 10 * (sceneItem.groundSpeed - (UAV.pathDesiredEndingVelocity() * qmlWidget.speedFactor))
anchors.verticalCenterOffset: speed_scale.height / 10 * (sceneItem.groundSpeed - (UAV.pathDesiredEndingVelocity() * pfdContext.speedFactor))
}
}
@ -98,7 +98,7 @@ Item {
elementName: "speed-box"
sceneSize: sceneItem.sceneSize
visible: qmlWidget.speedUnit != 0
visible: pfdContext.speedUnit != 0
x: scaledBounds.x * sceneItem.width
y: scaledBounds.y * sceneItem.height
@ -123,7 +123,7 @@ Item {
elementName: "speed-unit-box"
sceneSize: sceneItem.sceneSize
visible: qmlWidget.speedUnit != 0
visible: pfdContext.speedUnit != 0
anchors.top: speed_window.bottom
anchors.right: speed_window.right
@ -132,7 +132,7 @@ Item {
Text {
id: speed_unit_text
text: qmlWidget.speedUnit
text: pfdContext.speedUnit
color: "cyan"
font {
family: pt_bold.name

View File

@ -56,7 +56,7 @@ Item {
SvgElementImage {
id: vsi_scale_meter
visible: (qmlWidget.altitudeUnit == "m")
visible: (pfdContext.altitudeUnit == "m")
elementName: "vsi-scale-meter"
sceneSize: sceneItem.sceneSize
@ -68,7 +68,7 @@ Item {
SvgElementImage {
id: vsi_scale_ft
visible: (qmlWidget.altitudeUnit == "ft")
visible: (pfdContext.altitudeUnit == "ft")
elementName: "vsi-scale-ft"
sceneSize: sceneItem.sceneSize
@ -104,7 +104,7 @@ Item {
sceneSize: sceneItem.sceneSize
Text {
text: (qmlWidget.altitudeUnit == "m") ? "m/s" : "ft/s"
text: (pfdContext.altitudeUnit == "m") ? "m/s" : "ft/s"
color: "cyan"
font {
family: pt_bold.name

View File

@ -139,7 +139,7 @@ function homePosition() {
}
function defaultPosition() {
return Qt.vector3d(qmlWidget.longitude, qmlWidget.latitude, qmlWidget.altitude);
return Qt.vector3d(pfdContext.longitude, pfdContext.latitude, pfdContext.altitude);
}
/*