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:
commit
0b79fe9e6f
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
291
ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp
Normal file
291
ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp
Normal 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"
|
@ -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_
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ public:
|
||||
QWidget *widget();
|
||||
|
||||
void loadConfiguration(IUAVGadgetConfiguration *config);
|
||||
void saveState(QSettings *);
|
||||
void restoreState(QSettings *);
|
||||
|
||||
private:
|
||||
PfdQmlGadgetWidget *m_qmlGadgetWidget;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user