mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-11-29 07:24:13 +01:00
Merged in filnet/librepilot/filnet/LP-29_osgearth_integration (pull request #222)
LP-29_osgearth_integration
This commit is contained in:
commit
23f1867746
148
ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.cpp
Normal file
148
ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file DirtySupport.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @brief
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "DirtySupport.hpp"
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/NodeVisitor>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
class Hidden;
|
||||
|
||||
struct DirtySupport::NodeUpdateCallback : public osg::NodeCallback {
|
||||
public:
|
||||
NodeUpdateCallback(DirtySupport::Hidden *h) : h(h)
|
||||
{}
|
||||
|
||||
void operator()(osg::Node *node, osg::NodeVisitor *nv);
|
||||
|
||||
private:
|
||||
DirtySupport::Hidden *const h;
|
||||
};
|
||||
|
||||
struct DirtySupport::Hidden {
|
||||
private:
|
||||
DirtySupport *const self;
|
||||
|
||||
osg::ref_ptr<osg::NodeCallback> nodeUpdateCallback;
|
||||
|
||||
int dirtyFlags;
|
||||
|
||||
public:
|
||||
Hidden(DirtySupport *self) : self(self), dirtyFlags(0)
|
||||
{}
|
||||
|
||||
bool isDirty(int mask) const
|
||||
{
|
||||
return (dirtyFlags & mask) != 0;
|
||||
}
|
||||
|
||||
int dirty() const
|
||||
{
|
||||
return dirtyFlags;
|
||||
}
|
||||
|
||||
void setDirty(int mask)
|
||||
{
|
||||
// qDebug() << "DirtySupport::setDirty" << mask;
|
||||
if (!dirtyFlags) {
|
||||
osg::Node *node = self->nodeToUpdate();
|
||||
if (node) {
|
||||
if (!nodeUpdateCallback.valid()) {
|
||||
// lazy creation
|
||||
nodeUpdateCallback = new NodeUpdateCallback(this);
|
||||
}
|
||||
node->addUpdateCallback(nodeUpdateCallback.get());
|
||||
} else {
|
||||
// qWarning() << "DirtySupport::setDirty - node to update is null";
|
||||
}
|
||||
}
|
||||
dirtyFlags |= mask;
|
||||
}
|
||||
|
||||
void clearDirty()
|
||||
{
|
||||
osg::Node *node = self->nodeToUpdate();
|
||||
|
||||
if (node && nodeUpdateCallback.valid()) {
|
||||
node->removeUpdateCallback(nodeUpdateCallback.get());
|
||||
}
|
||||
dirtyFlags = 0;
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
// qDebug() << "DirtySupport::update";
|
||||
if (dirtyFlags) {
|
||||
// qDebug() << "DirtySupport::update - updating...";
|
||||
self->update();
|
||||
}
|
||||
clearDirty();
|
||||
}
|
||||
};
|
||||
|
||||
/* struct DirtySupport::NodeUpdateCallback */
|
||||
|
||||
void DirtySupport::NodeUpdateCallback::operator()(osg::Node *node, osg::NodeVisitor *nv)
|
||||
{
|
||||
// qDebug() << "DirtySupport::NodeUpdateCallback";
|
||||
nv->traverse(*node);
|
||||
h->update();
|
||||
}
|
||||
|
||||
/* class DirtySupport */
|
||||
|
||||
DirtySupport::DirtySupport() : h(new Hidden(this))
|
||||
{}
|
||||
|
||||
DirtySupport::~DirtySupport()
|
||||
{
|
||||
delete h;
|
||||
}
|
||||
|
||||
int DirtySupport::dirty() const
|
||||
{
|
||||
return h->dirty();
|
||||
}
|
||||
|
||||
bool DirtySupport::isDirty(int mask) const
|
||||
{
|
||||
return h->isDirty(mask);
|
||||
}
|
||||
|
||||
void DirtySupport::setDirty(int mask)
|
||||
{
|
||||
h->setDirty(mask);
|
||||
}
|
||||
|
||||
void DirtySupport::clearDirty()
|
||||
{
|
||||
h->clearDirty();
|
||||
}
|
||||
} // namespace osgQtQuick
|
63
ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.hpp
Normal file
63
ground/gcs/src/libs/osgearth/osgQtQuick/DirtySupport.hpp
Normal file
@ -0,0 +1,63 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file DirtySupport.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @brief
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _H_OSGQTQUICK_DIRTYSUPPORT_H_
|
||||
#define _H_OSGQTQUICK_DIRTYSUPPORT_H_
|
||||
|
||||
namespace osg {
|
||||
class Node;
|
||||
} // namespace osg
|
||||
|
||||
namespace osgQtQuick {
|
||||
/**
|
||||
* Provides support to:
|
||||
* - manage dirty state flags
|
||||
* - add/remove node callback to trigger refresh (compatible with viewer on demand mode)
|
||||
*/
|
||||
class DirtySupport {
|
||||
public:
|
||||
explicit DirtySupport();
|
||||
virtual ~DirtySupport();
|
||||
|
||||
protected:
|
||||
int dirty() const;
|
||||
bool isDirty(int mask = 0xFFFF) const;
|
||||
void setDirty(int mask = 0xFFFF);
|
||||
void clearDirty();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
struct NodeUpdateCallback;
|
||||
Hidden *const h;
|
||||
|
||||
virtual osg::Node *nodeToUpdate() const = 0;
|
||||
|
||||
virtual void update() = 0;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#endif // _H_OSGQTQUICK_DIRTYSUPPORT_H_
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file Export.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
|
@ -1,128 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGBackgroundNode.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 "OSGBackgroundNode.hpp"
|
||||
|
||||
#include <osg/Depth>
|
||||
#include <osg/Texture2D>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <QUrl>
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
struct OSGBackgroundNode::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OSGBackgroundNode * const self;
|
||||
|
||||
public:
|
||||
QUrl url;
|
||||
|
||||
Hidden(OSGBackgroundNode *parent) : QObject(parent), self(parent), url() {}
|
||||
|
||||
void updateNode()
|
||||
{
|
||||
// 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());
|
||||
|
||||
texture->setImage(image.get());
|
||||
|
||||
osg::ref_ptr<osg::Drawable> quad = osg::createTexturedQuadGeometry(
|
||||
osg::Vec3(), osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 1.0f, 0.0f));
|
||||
quad->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture.get());
|
||||
|
||||
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
|
||||
geode->addDrawable(quad.get());
|
||||
|
||||
osg::Camera *camera = new osg::Camera;
|
||||
camera->setClearMask(0);
|
||||
camera->setCullingActive(false);
|
||||
camera->setAllowEventFocus(false);
|
||||
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
camera->setRenderOrder(osg::Camera::POST_RENDER);
|
||||
camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0, 1.0, 0.0, 1.0));
|
||||
camera->addChild(geode.get());
|
||||
|
||||
osg::StateSet *ss = camera->getOrCreateStateSet();
|
||||
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
ss->setAttributeAndModes(new osg::Depth(osg::Depth::LEQUAL, 1.0, 1.0));
|
||||
|
||||
self->setNode(camera);
|
||||
}
|
||||
};
|
||||
|
||||
/* class OSGBackgroundNode */
|
||||
|
||||
enum DirtyFlag { URL = 1 << 0 };
|
||||
|
||||
OSGBackgroundNode::OSGBackgroundNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
|
||||
{
|
||||
qDebug() << "OSGBackgroundNode::OSGBackgroundNode";
|
||||
}
|
||||
|
||||
OSGBackgroundNode::~OSGBackgroundNode()
|
||||
{
|
||||
// qDebug() << "OSGBackgroundNode::~OSGBackgroundNode";
|
||||
delete h;
|
||||
}
|
||||
|
||||
const QUrl OSGBackgroundNode::imageFile() const
|
||||
{
|
||||
return h->url;
|
||||
}
|
||||
|
||||
void OSGBackgroundNode::setImageFile(const QUrl &url)
|
||||
{
|
||||
// qDebug() << "OSGBackgroundNode::setImageFile" << url;
|
||||
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"
|
94
ground/gcs/src/libs/osgearth/osgQtQuick/OSGBillboardNode.cpp
Normal file
94
ground/gcs/src/libs/osgearth/osgQtQuick/OSGBillboardNode.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGBillboardNode.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @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 "OSGBillboardNode.hpp"
|
||||
|
||||
#include <osg/Depth>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/ImageSequence>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
// NOTE : these flags should not overlap with OSGGroup flags!!!
|
||||
// TODO : find a better way...
|
||||
enum DirtyFlag {};
|
||||
|
||||
struct OSGBillboardNode::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OSGBillboardNode * const self;
|
||||
|
||||
osg::ref_ptr<osg::Camera> camera;
|
||||
|
||||
public:
|
||||
Hidden(OSGBillboardNode *self) : QObject(self), self(self)
|
||||
{}
|
||||
|
||||
osg::Node *createNode()
|
||||
{
|
||||
camera = new osg::Camera;
|
||||
camera->setClearMask(0);
|
||||
camera->setCullingActive(false);
|
||||
camera->setAllowEventFocus(false);
|
||||
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
camera->setRenderOrder(osg::Camera::POST_RENDER);
|
||||
camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0, 1.0, 0.0, 1.0));
|
||||
|
||||
osg::StateSet *ss = camera->getOrCreateStateSet();
|
||||
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
ss->setAttributeAndModes(new osg::Depth(osg::Depth::LEQUAL, 1.0, 1.0));
|
||||
|
||||
return camera;
|
||||
}
|
||||
};
|
||||
|
||||
/* class OSGBillboardNode */
|
||||
|
||||
OSGBillboardNode::OSGBillboardNode(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
OSGBillboardNode::~OSGBillboardNode()
|
||||
{
|
||||
delete h;
|
||||
}
|
||||
|
||||
osg::Node *OSGBillboardNode::createNode()
|
||||
{
|
||||
return h->createNode();
|
||||
}
|
||||
|
||||
void OSGBillboardNode::updateNode()
|
||||
{
|
||||
Inherited::updateNode();
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGBillboardNode.moc"
|
54
ground/gcs/src/libs/osgearth/osgQtQuick/OSGBillboardNode.hpp
Normal file
54
ground/gcs/src/libs/osgearth/osgQtQuick/OSGBillboardNode.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGBillboardNode.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @brief
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _H_OSGQTQUICK_BILLBOARDNODE_H_
|
||||
#define _H_OSGQTQUICK_BILLBOARDNODE_H_
|
||||
|
||||
#include "Export.hpp"
|
||||
#include "OSGGroup.hpp"
|
||||
|
||||
namespace osgQtQuick {
|
||||
class OSGQTQUICK_EXPORT OSGBillboardNode : public OSGGroup {
|
||||
Q_OBJECT
|
||||
|
||||
typedef OSGGroup Inherited;
|
||||
|
||||
public:
|
||||
OSGBillboardNode(QObject *parent = 0);
|
||||
virtual ~OSGBillboardNode();
|
||||
|
||||
protected:
|
||||
virtual osg::Node *createNode();
|
||||
virtual void updateNode();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#endif // _H_OSGQTQUICK_BILLBOARDNODE_H_
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGCamera.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -27,41 +27,45 @@
|
||||
|
||||
#include "OSGCamera.hpp"
|
||||
|
||||
#include "OSGNode.hpp"
|
||||
|
||||
#include "../utility.h"
|
||||
|
||||
#include <osg/Camera>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Node>
|
||||
#include <osg/Vec3d>
|
||||
|
||||
#include <osgGA/NodeTrackerManipulator>
|
||||
#include <osgGA/TrackballManipulator>
|
||||
|
||||
#include <osgViewer/View>
|
||||
|
||||
#ifdef USE_OSGEARTH
|
||||
#include <osgEarthUtil/EarthManipulator>
|
||||
#include <osgEarthUtil/LogarithmicDepthBuffer>
|
||||
#endif
|
||||
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
#include <QApplication>
|
||||
|
||||
namespace osgQtQuick {
|
||||
enum DirtyFlag { FieldOfView = 1 << 0, ClearColor = 1 << 1, LogDepthBuffer = 1 << 4 };
|
||||
|
||||
struct OSGCamera::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
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;
|
||||
private:
|
||||
OSGCamera * const self;
|
||||
|
||||
osg::ref_ptr<osg::Camera> camera;
|
||||
|
||||
public:
|
||||
// Camera vertical field of view in degrees
|
||||
// fov depends on the scenery space (probably distance)
|
||||
// here are some value: 75°, 60°, 45° many gamers use
|
||||
// x-plane uses 45° for 4:3 and 60° for 16:9/16:10
|
||||
// flightgear uses 55° / 70°
|
||||
qreal fieldOfView;
|
||||
|
||||
QColor clearColor;
|
||||
|
||||
bool logDepthBufferEnabled;
|
||||
|
||||
#ifdef USE_OSGEARTH
|
||||
osgEarth::Util::LogarithmicDepthBuffer *logDepthBuffer;
|
||||
#endif
|
||||
|
||||
public:
|
||||
Hidden(OSGCamera *self) : QObject(self), self(self), fieldOfView(90), clearColor(0, 0, 0, 255), logDepthBufferEnabled(false)
|
||||
{
|
||||
#ifdef USE_OSGEARTH
|
||||
logDepthBuffer = NULL;
|
||||
#endif
|
||||
@ -69,97 +73,6 @@ public:
|
||||
|
||||
~Hidden()
|
||||
{
|
||||
#ifdef USE_OSGEARTH
|
||||
if (logDepthBuffer) {
|
||||
delete logDepthBuffer;
|
||||
logDepthBuffer = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool acceptSceneNode(OSGNode *node)
|
||||
{
|
||||
qDebug() << "OSGCamera::acceptSceneNode" << node;
|
||||
if (sceneNode == node) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sceneNode) {
|
||||
disconnect(sceneNode);
|
||||
}
|
||||
|
||||
sceneNode = node;
|
||||
|
||||
if (sceneNode) {
|
||||
connect(sceneNode, &OSGNode::nodeChanged, this, &Hidden::onSceneNodeChanged);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool acceptManipulatorMode(ManipulatorMode::Enum mode)
|
||||
{
|
||||
// qDebug() << "OSGCamera::acceptManipulatorMode" << mode;
|
||||
if (manipulatorMode == mode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
manipulatorMode = mode;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool acceptTrackNode(OSGNode *node)
|
||||
{
|
||||
qDebug() << "OSGCamera::acceptTrackNode" << node;
|
||||
if (trackNode == node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (trackNode) {
|
||||
disconnect(trackNode);
|
||||
}
|
||||
|
||||
trackNode = node;
|
||||
|
||||
if (trackNode) {
|
||||
connect(trackNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onTrackNodeChanged(osg::Node *)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void attachCamera(osg::Camera *camera)
|
||||
{
|
||||
qDebug() << "OSGCamera::attach" << camera;
|
||||
|
||||
this->camera = camera;
|
||||
self->setNode(this->camera.get());
|
||||
|
||||
#ifdef USE_OSGEARTH
|
||||
// install log depth buffer if requested
|
||||
if (logDepthBufferEnabled) {
|
||||
qDebug() << "OSGCamera::attach - install logarithmic depth buffer";
|
||||
logDepthBuffer = new osgEarth::Util::LogarithmicDepthBuffer();
|
||||
logDepthBuffer->setUseFragDepth(true);
|
||||
logDepthBuffer->install(camera);
|
||||
}
|
||||
#endif
|
||||
|
||||
updateFieldOfView();
|
||||
updateAspectRatio();
|
||||
}
|
||||
|
||||
void detachCamera(osg::Camera *camera)
|
||||
{
|
||||
qDebug() << "OSGCamera::detach" << camera;
|
||||
|
||||
if (camera != this->camera) {
|
||||
qWarning() << "OSGCamera::detach - camera not attached" << camera;
|
||||
return;
|
||||
}
|
||||
this->camera = NULL;
|
||||
|
||||
#ifdef USE_OSGEARTH
|
||||
if (logDepthBuffer) {
|
||||
logDepthBuffer->uninstall(camera);
|
||||
@ -169,93 +82,36 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
void attachManipulator(osgViewer::View *view)
|
||||
osg::Node *createNode()
|
||||
{
|
||||
qDebug() << "OSGCamera::attachManipulator" << view;
|
||||
camera = new osg::Camera();
|
||||
|
||||
osgGA::CameraManipulator *cm = NULL;
|
||||
camera->setClearColor(osg::Vec4(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF()));
|
||||
|
||||
switch (manipulatorMode) {
|
||||
case ManipulatorMode::Default:
|
||||
{
|
||||
qDebug() << "OSGCamera::attachManipulator - use TrackballManipulator";
|
||||
osgGA::TrackballManipulator *tm = new osgGA::TrackballManipulator();
|
||||
// Set the minimum distance of the eye point from the center before the center is pushed forward.
|
||||
// tm->setMinimumDistance(1, true);
|
||||
cm = tm;
|
||||
break;
|
||||
}
|
||||
case ManipulatorMode::User:
|
||||
qDebug() << "OSGCamera::attachManipulator - no camera manipulator";
|
||||
// disable any installed camera manipulator
|
||||
// TODO create and use own camera manipulator to avoid disabling ON_DEMAND frame update scheme
|
||||
// see https://github.com/gwaldron/osgearth/commit/796daf4792ccaf18ae7eb6a5cb268eef0d42888d
|
||||
// TODO see StandardManipulator for an example on how to react to events (to have FOV changes without the need for an update callback?)
|
||||
cm = NULL;
|
||||
break;
|
||||
case ManipulatorMode::Earth:
|
||||
{
|
||||
#ifdef USE_OSGEARTH
|
||||
qDebug() << "OSGCamera::attachManipulator - use EarthManipulator";
|
||||
osgEarth::Util::EarthManipulator *em = new osgEarth::Util::EarthManipulator();
|
||||
em->getSettings()->setThrowingEnabled(true);
|
||||
cm = em;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case ManipulatorMode::Track:
|
||||
qDebug() << "OSGCamera::attachManipulator - use NodeTrackerManipulator";
|
||||
if (trackNode && trackNode->node()) {
|
||||
// setup tracking camera
|
||||
// TODO when camera is thrown, then changing attitude has jitter
|
||||
osgGA::NodeTrackerManipulator *ntm = new osgGA::NodeTrackerManipulator(
|
||||
/*osgGA::StandardManipulator::COMPUTE_HOME_USING_BBOX | osgGA::StandardManipulator::DEFAULT_SETTINGS*/);
|
||||
switch (trackerMode) {
|
||||
case TrackerMode::NodeCenter:
|
||||
ntm->setTrackerMode(osgGA::NodeTrackerManipulator::NODE_CENTER);
|
||||
break;
|
||||
case TrackerMode::NodeCenterAndAzim:
|
||||
ntm->setTrackerMode(osgGA::NodeTrackerManipulator::NODE_CENTER_AND_AZIM);
|
||||
break;
|
||||
case TrackerMode::NodeCenterAndRotation:
|
||||
ntm->setTrackerMode(osgGA::NodeTrackerManipulator::NODE_CENTER_AND_ROTATION);
|
||||
break;
|
||||
}
|
||||
ntm->setTrackNode(trackNode->node());
|
||||
ntm->setVerticalAxisFixed(false);
|
||||
cm = ntm;
|
||||
} else {
|
||||
qWarning() << "OSGCamera::attachManipulator - no track node provided.";
|
||||
cm = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
qWarning() << "OSGCamera::attachManipulator - should not reach here!";
|
||||
break;
|
||||
}
|
||||
osg::StateSet *stateset = camera->getOrCreateStateSet();
|
||||
stateset->setGlobalDefaults();
|
||||
|
||||
view->setCameraManipulator(cm, false);
|
||||
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(sceneNode->node());
|
||||
}
|
||||
if (cm) {
|
||||
view->home();
|
||||
}
|
||||
return camera;
|
||||
}
|
||||
|
||||
void detachManipulator(osgViewer::View *view)
|
||||
void updateClearColor()
|
||||
{
|
||||
qDebug() << "OSGCamera::detachManipulator" << view;
|
||||
|
||||
view->setCameraManipulator(NULL, false);
|
||||
if (!camera.valid()) {
|
||||
qDebug() << "OSGCamera::updateClearColor - invalid camera";
|
||||
return;
|
||||
}
|
||||
// qDebug() << "OSGCamera::updateClearColor" << clearColor;
|
||||
camera->setClearColor(osg::Vec4(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF()));
|
||||
}
|
||||
|
||||
void updateFieldOfView()
|
||||
{
|
||||
qDebug() << "OSGCamera::updateCameraFOV" << fieldOfView;
|
||||
if (!camera.valid()) {
|
||||
qDebug() << "OSGCamera::updateFieldOfView - invalid camera";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "OSGCamera::updateFieldOfView" << fieldOfView;
|
||||
|
||||
double fovy, ar, zn, zf;
|
||||
camera->getProjectionMatrixAsPerspective(fovy, ar, zn, zf);
|
||||
@ -265,7 +121,16 @@ public:
|
||||
|
||||
void updateAspectRatio()
|
||||
{
|
||||
if (!camera.valid()) {
|
||||
qDebug() << "OSGCamera::updateAspectRatio - invalid camera";
|
||||
return;
|
||||
}
|
||||
osg::Viewport *viewport = camera->getViewport();
|
||||
if (!viewport) {
|
||||
qDebug() << "OSGCamera::updateAspectRatio - no viewport" << viewport;
|
||||
return;
|
||||
}
|
||||
|
||||
double aspectRatio = static_cast<double>(viewport->width()) / static_cast<double>(viewport->height());
|
||||
|
||||
qDebug() << "OSGCamera::updateAspectRatio" << aspectRatio;
|
||||
@ -276,113 +141,77 @@ public:
|
||||
camera->setProjectionMatrixAsPerspective(fovy, ar, zn, zf);
|
||||
}
|
||||
|
||||
void updatePosition()
|
||||
void updateLogDepthBuffer()
|
||||
{
|
||||
if (manipulatorMode != ManipulatorMode::User) {
|
||||
if (!camera.valid()) {
|
||||
qWarning() << "OSGCamera::updateLogDepthBuffer - invalid camera";
|
||||
return;
|
||||
}
|
||||
// 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.
|
||||
// TODO handle the case where the terrain SRS is not "wgs84"
|
||||
// TODO check if position is not below terrain?
|
||||
// TODO compensate antenna height when source of position is GPS (i.e. subtract antenna height from altitude) ;)
|
||||
|
||||
// Camera position
|
||||
osg::Matrix cameraPosition;
|
||||
// qDebug() << "OSGCamera::updateLogDepthBuffer" << logDepthBufferEnabled;
|
||||
|
||||
#ifdef USE_OSGEARTH
|
||||
osgEarth::GeoPoint geoPoint = osgQtQuick::toGeoPoint(position);
|
||||
if (clampToTerrain) {
|
||||
if (sceneNode) {
|
||||
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
|
||||
if (mapNode) {
|
||||
intoTerrain = clampGeoPoint(geoPoint, 0.5f, mapNode);
|
||||
} else {
|
||||
qWarning() << "OSGCamera::updateNode - scene data does not contain a map node";
|
||||
}
|
||||
}
|
||||
// install log depth buffer if requested
|
||||
if (logDepthBufferEnabled && !logDepthBuffer) {
|
||||
qDebug() << "OSGCamera::updateLogDepthBuffer - installing logarithmic depth buffer";
|
||||
logDepthBuffer = new osgEarth::Util::LogarithmicDepthBuffer();
|
||||
logDepthBuffer->setUseFragDepth(true);
|
||||
logDepthBuffer->install(camera);
|
||||
} else if (!logDepthBufferEnabled && logDepthBuffer) {
|
||||
qDebug() << "OSGCamera::updateLogDepthBuffer - uninstalling logarithmic depth buffer";
|
||||
logDepthBuffer->uninstall(camera);
|
||||
delete logDepthBuffer;
|
||||
logDepthBuffer = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void setGraphicsContext(osg::GraphicsContext *gc)
|
||||
{
|
||||
if (!camera.valid()) {
|
||||
qDebug() << "OSGCamera::setGraphicsContext - invalid camera";
|
||||
return;
|
||||
}
|
||||
|
||||
geoPoint.createLocalToWorld(cameraPosition);
|
||||
#endif
|
||||
qDebug() << "OSGCamera::setGraphicsContext" << gc;
|
||||
|
||||
// Camera orientation
|
||||
// By default the camera looks toward -Z, we must rotate it so it looks toward Y
|
||||
osg::Matrix cameraRotation;
|
||||
cameraRotation.makeRotate(osg::DegreesToRadians(90.0), osg::Vec3(1.0, 0.0, 0.0),
|
||||
osg::DegreesToRadians(0.0), osg::Vec3(0.0, 1.0, 0.0),
|
||||
osg::DegreesToRadians(0.0), osg::Vec3(0.0, 0.0, 1.0));
|
||||
camera->setGraphicsContext(gc);
|
||||
camera->setViewport(0, 0, gc->getTraits()->width, gc->getTraits()->height);
|
||||
|
||||
// Final camera matrix
|
||||
double roll = osg::DegreesToRadians(attitude.x());
|
||||
double pitch = osg::DegreesToRadians(attitude.y());
|
||||
double yaw = osg::DegreesToRadians(attitude.z());
|
||||
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)) * cameraPosition;
|
||||
double aspectRatio = static_cast<double>(gc->getTraits()->width) / static_cast<double>(gc->getTraits()->height);
|
||||
|
||||
// Inverse the camera's position and orientation matrix to obtain the view matrix
|
||||
cameraMatrix = osg::Matrix::inverse(cameraMatrix);
|
||||
camera->setViewMatrix(cameraMatrix);
|
||||
}
|
||||
camera->setProjectionMatrixAsPerspective(fieldOfView, aspectRatio, 1.0f, 10000.0f);
|
||||
|
||||
OSGCamera *const self;
|
||||
double fovy, ar, zn, zf;
|
||||
camera->getProjectionMatrixAsPerspective(fovy, ar, zn, zf);
|
||||
|
||||
osg::ref_ptr<osg::Camera> camera;
|
||||
|
||||
// Camera vertical field of view in degrees
|
||||
qreal fieldOfView;
|
||||
|
||||
OSGNode *sceneNode;
|
||||
|
||||
ManipulatorMode::Enum manipulatorMode;
|
||||
|
||||
// for NodeTrackerManipulator
|
||||
TrackerMode::Enum trackerMode;
|
||||
OSGNode *trackNode;
|
||||
|
||||
bool logDepthBufferEnabled;
|
||||
#ifdef USE_OSGEARTH
|
||||
osgEarth::Util::LogarithmicDepthBuffer *logDepthBuffer;
|
||||
#endif
|
||||
|
||||
bool clampToTerrain;
|
||||
bool intoTerrain;
|
||||
|
||||
QVector3D attitude;
|
||||
QVector3D position;
|
||||
|
||||
private slots:
|
||||
void onSceneNodeChanged(osg::Node *node)
|
||||
{
|
||||
qDebug() << "OSGCamera::onSceneNodeChanged" << node;
|
||||
qWarning() << "OSGCamera::onSceneNodeChanged - needs to be implemented";
|
||||
}
|
||||
|
||||
void onTrackNodeChanged(osg::Node *node)
|
||||
{
|
||||
qDebug() << "OSGCamera::onTrackNodeChanged" << node;
|
||||
qWarning() << "OSGCamera::onTrackNodeChanged - needs to be implemented";
|
||||
// FIXME this is needed for PFD + Terrain (because of "user" mode)
|
||||
// updatePosition();
|
||||
}
|
||||
};
|
||||
|
||||
/* class OSGCamera */
|
||||
|
||||
enum DirtyFlag { FieldOfView = 1 << 0, Position = 1 << 1, Attitude = 1 << 2 };
|
||||
|
||||
OSGCamera::OSGCamera(QObject *parent) : OSGNode(parent), h(new Hidden(this))
|
||||
{
|
||||
qDebug() << "OSGCamera::OSGCamera";
|
||||
}
|
||||
OSGCamera::OSGCamera(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
OSGCamera::~OSGCamera()
|
||||
{
|
||||
qDebug() << "OSGCamera::~OSGCamera";
|
||||
delete h;
|
||||
}
|
||||
|
||||
QColor OSGCamera::clearColor() const
|
||||
{
|
||||
return h->clearColor;
|
||||
}
|
||||
|
||||
void OSGCamera::setClearColor(const QColor &color)
|
||||
{
|
||||
if (h->clearColor != color) {
|
||||
h->clearColor = color;
|
||||
emit clearColorChanged(color);
|
||||
}
|
||||
}
|
||||
|
||||
qreal OSGCamera::fieldOfView() const
|
||||
{
|
||||
return h->fieldOfView;
|
||||
@ -397,102 +226,7 @@ void OSGCamera::setFieldOfView(qreal arg)
|
||||
}
|
||||
}
|
||||
|
||||
OSGNode *OSGCamera::sceneNode()
|
||||
{
|
||||
return h->sceneNode;
|
||||
}
|
||||
|
||||
void OSGCamera::setSceneNode(OSGNode *node)
|
||||
{
|
||||
if (h->acceptSceneNode(node)) {
|
||||
emit sceneNodeChanged(node);
|
||||
}
|
||||
}
|
||||
|
||||
ManipulatorMode::Enum OSGCamera::manipulatorMode() const
|
||||
{
|
||||
return h->manipulatorMode;
|
||||
}
|
||||
|
||||
void OSGCamera::setManipulatorMode(ManipulatorMode::Enum mode)
|
||||
{
|
||||
if (h->acceptManipulatorMode(mode)) {
|
||||
emit manipulatorModeChanged(manipulatorMode());
|
||||
}
|
||||
}
|
||||
|
||||
OSGNode *OSGCamera::trackNode() const
|
||||
{
|
||||
return h->trackNode;
|
||||
}
|
||||
|
||||
void OSGCamera::setTrackNode(OSGNode *node)
|
||||
{
|
||||
if (h->acceptTrackNode(node)) {
|
||||
emit trackNodeChanged(node);
|
||||
}
|
||||
}
|
||||
|
||||
TrackerMode::Enum OSGCamera::trackerMode() const
|
||||
{
|
||||
return h->trackerMode;
|
||||
}
|
||||
|
||||
void OSGCamera::setTrackerMode(TrackerMode::Enum mode)
|
||||
{
|
||||
if (h->trackerMode != mode) {
|
||||
h->trackerMode = mode;
|
||||
emit trackerModeChanged(trackerMode());
|
||||
}
|
||||
}
|
||||
|
||||
bool OSGCamera::clampToTerrain() const
|
||||
{
|
||||
return h->clampToTerrain;
|
||||
}
|
||||
|
||||
void OSGCamera::setClampToTerrain(bool arg)
|
||||
{
|
||||
if (h->clampToTerrain != arg) {
|
||||
h->clampToTerrain = arg;
|
||||
emit clampToTerrainChanged(clampToTerrain());
|
||||
}
|
||||
}
|
||||
|
||||
bool OSGCamera::intoTerrain() const
|
||||
{
|
||||
return h->intoTerrain;
|
||||
}
|
||||
|
||||
QVector3D OSGCamera::attitude() const
|
||||
{
|
||||
return h->attitude;
|
||||
}
|
||||
|
||||
void OSGCamera::setAttitude(QVector3D arg)
|
||||
{
|
||||
if (h->attitude != arg) {
|
||||
h->attitude = arg;
|
||||
setDirty(Attitude);
|
||||
emit attitudeChanged(attitude());
|
||||
}
|
||||
}
|
||||
|
||||
QVector3D OSGCamera::position() const
|
||||
{
|
||||
return h->position;
|
||||
}
|
||||
|
||||
void OSGCamera::setPosition(QVector3D arg)
|
||||
{
|
||||
if (h->position != arg) {
|
||||
h->position = arg;
|
||||
setDirty(Position);
|
||||
emit positionChanged(position());
|
||||
}
|
||||
}
|
||||
|
||||
bool OSGCamera::logarithmicDepthBuffer()
|
||||
bool OSGCamera::logarithmicDepthBuffer() const
|
||||
{
|
||||
return h->logDepthBufferEnabled;
|
||||
}
|
||||
@ -501,32 +235,40 @@ void OSGCamera::setLogarithmicDepthBuffer(bool enabled)
|
||||
{
|
||||
if (h->logDepthBufferEnabled != enabled) {
|
||||
h->logDepthBufferEnabled = enabled;
|
||||
setDirty(LogDepthBuffer);
|
||||
emit logarithmicDepthBufferChanged(logarithmicDepthBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
void OSGCamera::update()
|
||||
osg::Node *OSGCamera::createNode()
|
||||
{
|
||||
return h->createNode();
|
||||
}
|
||||
|
||||
void OSGCamera::updateNode()
|
||||
{
|
||||
Inherited::updateNode();
|
||||
|
||||
if (isDirty(ClearColor)) {
|
||||
h->updateClearColor();
|
||||
}
|
||||
if (isDirty(FieldOfView)) {
|
||||
h->updateFieldOfView();
|
||||
}
|
||||
if (isDirty(Position | Attitude)) {
|
||||
h->updatePosition();
|
||||
if (isDirty(LogDepthBuffer)) {
|
||||
h->updateLogDepthBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
void OSGCamera::attach(osgViewer::View *view)
|
||||
osg::Camera *OSGCamera::asCamera() const
|
||||
{
|
||||
h->attachCamera(view->getCamera());
|
||||
h->attachManipulator(view);
|
||||
update();
|
||||
clearDirty();
|
||||
// BAD introduce templating
|
||||
return (osg::Camera *)node();
|
||||
}
|
||||
|
||||
void OSGCamera::detach(osgViewer::View *view)
|
||||
void OSGCamera::setGraphicsContext(osg::GraphicsContext *gc)
|
||||
{
|
||||
h->detachManipulator(view);
|
||||
h->detachCamera(view->getCamera());
|
||||
h->setGraphicsContext(gc);
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGCamera.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -32,114 +32,51 @@
|
||||
#include "OSGNode.hpp"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector3D>
|
||||
#include <QColor>
|
||||
|
||||
namespace osgViewer {
|
||||
class View;
|
||||
namespace osg {
|
||||
class Camera;
|
||||
class GraphicsContext;
|
||||
}
|
||||
|
||||
namespace osgQtQuick {
|
||||
class ManipulatorMode : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Enum { Default, Earth, Track, User };
|
||||
Q_ENUMS(Enum) // TODO switch to Q_ENUM once on Qt 5.5
|
||||
};
|
||||
|
||||
class TrackerMode : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Enum { NodeCenter, NodeCenterAndAzim, NodeCenterAndRotation };
|
||||
Q_ENUMS(Enum) // TODO switch to Q_ENUM once on Qt 5.5
|
||||
};
|
||||
|
||||
// This class does too much:
|
||||
// - tracking a geo point and attitude
|
||||
// - tracking another node
|
||||
// camera should be simpler and provide only tracking
|
||||
// - tracking of a modelnode (for ModelView)
|
||||
// - tracking of a virtual node (for PFD with Terrain)
|
||||
//
|
||||
// TODO
|
||||
// - expose track mode
|
||||
// - provide good default distance and attitude for tracker camera
|
||||
class OSGQTQUICK_EXPORT OSGCamera : public OSGNode {
|
||||
Q_OBJECT Q_PROPERTY(qreal fieldOfView READ fieldOfView WRITE setFieldOfView NOTIFY fieldOfViewChanged)
|
||||
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 * 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)
|
||||
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)
|
||||
Q_OBJECT Q_PROPERTY(QColor clearColor READ clearColor WRITE setClearColor NOTIFY clearColorChanged)
|
||||
Q_PROPERTY(qreal fieldOfView READ fieldOfView WRITE setFieldOfView NOTIFY fieldOfViewChanged)
|
||||
Q_PROPERTY(bool logarithmicDepthBuffer READ logarithmicDepthBuffer WRITE setLogarithmicDepthBuffer NOTIFY logarithmicDepthBufferChanged)
|
||||
|
||||
typedef OSGNode Inherited;
|
||||
|
||||
friend class OSGViewport;
|
||||
|
||||
public:
|
||||
explicit OSGCamera(QObject *parent = 0);
|
||||
virtual ~OSGCamera();
|
||||
|
||||
// fov depends on the scenery space (probaby distance)
|
||||
// here are some value: 75°, 60°, 45° many gamers use
|
||||
// x-plane uses 45° for 4:3 and 60° for 16:9/16:10
|
||||
// flightgear uses 55° / 70°
|
||||
QColor clearColor() const;
|
||||
void setClearColor(const QColor &color);
|
||||
|
||||
qreal fieldOfView() const;
|
||||
void setFieldOfView(qreal arg);
|
||||
|
||||
OSGNode *sceneNode();
|
||||
void setSceneNode(OSGNode *node);
|
||||
|
||||
ManipulatorMode::Enum manipulatorMode() const;
|
||||
void setManipulatorMode(ManipulatorMode::Enum);
|
||||
|
||||
OSGNode *trackNode() const;
|
||||
void setTrackNode(OSGNode *node);
|
||||
|
||||
TrackerMode::Enum trackerMode() const;
|
||||
void setTrackerMode(TrackerMode::Enum);
|
||||
|
||||
bool clampToTerrain() const;
|
||||
void setClampToTerrain(bool arg);
|
||||
|
||||
bool intoTerrain() const;
|
||||
|
||||
QVector3D attitude() const;
|
||||
void setAttitude(QVector3D arg);
|
||||
|
||||
QVector3D position() const;
|
||||
void setPosition(QVector3D arg);
|
||||
|
||||
bool logarithmicDepthBuffer();
|
||||
bool logarithmicDepthBuffer() const;
|
||||
void setLogarithmicDepthBuffer(bool enabled);
|
||||
|
||||
signals:
|
||||
void clearColorChanged(const QColor &color);
|
||||
void fieldOfViewChanged(qreal arg);
|
||||
|
||||
void sceneNodeChanged(OSGNode *node);
|
||||
|
||||
void manipulatorModeChanged(ManipulatorMode::Enum);
|
||||
|
||||
void trackNodeChanged(OSGNode *node);
|
||||
void trackerModeChanged(TrackerMode::Enum);
|
||||
|
||||
void clampToTerrainChanged(bool arg);
|
||||
void intoTerrainChanged(bool arg);
|
||||
|
||||
void attitudeChanged(QVector3D arg);
|
||||
void positionChanged(QVector3D arg);
|
||||
|
||||
void logarithmicDepthBufferChanged(bool enabled);
|
||||
|
||||
protected:
|
||||
virtual osg::Node *createNode();
|
||||
virtual void updateNode();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *h;
|
||||
Hidden *const h;
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual void attach(osgViewer::View *view);
|
||||
virtual void detach(osgViewer::View *view);
|
||||
osg::Camera *asCamera() const;
|
||||
void setGraphicsContext(osg::GraphicsContext *gc);
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGFileNode.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -37,11 +37,14 @@
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
enum DirtyFlag { Source = 1 << 0, Async = 1 << 1, OptimizeMode = 1 << 2 };
|
||||
|
||||
class OSGFileLoader : public QThread {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
OSGFileLoader(const QUrl &url) : url(url) {}
|
||||
OSGFileLoader(const QUrl &url) : url(url)
|
||||
{}
|
||||
|
||||
void run()
|
||||
{
|
||||
@ -54,9 +57,12 @@ public:
|
||||
QElapsedTimer t;
|
||||
|
||||
t.start();
|
||||
qDebug() << "OSGFileLoader::load - reading node file" << url.path();
|
||||
// qDebug() << "OSGFileLoader::load - reading node file" << url.path();
|
||||
// qDebug() << "OSGFileLoader - load - currentContext" << QOpenGLContext::currentContext();
|
||||
osg::Node *node = osgDB::readNodeFile(url.path().toStdString());
|
||||
if (!node) {
|
||||
qWarning() << "OSGFileLoader::load - failed to load" << url.path();
|
||||
}
|
||||
// qDebug() << "OSGFileLoader::load - reading node" << node << "took" << t.elapsed() << "ms";
|
||||
return node;
|
||||
}
|
||||
@ -79,11 +85,12 @@ public:
|
||||
bool async;
|
||||
OptimizeMode::Enum optimizeMode;
|
||||
|
||||
Hidden(OSGFileNode *node) : QObject(node), self(node), source(), async(false), optimizeMode(OptimizeMode::None) {}
|
||||
Hidden(OSGFileNode *self) : QObject(self), self(self), source(), async(false), optimizeMode(OptimizeMode::None)
|
||||
{}
|
||||
|
||||
void updateNode()
|
||||
void updateSource()
|
||||
{
|
||||
// qDebug() << "OSGFileNode::updateNode" << source;
|
||||
qDebug() << "OSGFileNode::updateNode" << source;
|
||||
if (!source.isValid()) {
|
||||
self->setNode(NULL);
|
||||
if (!source.isEmpty()) {
|
||||
@ -118,7 +125,7 @@ private:
|
||||
|
||||
void setNode(osg::Node *node)
|
||||
{
|
||||
qDebug() << "OSGFileNode::setNode" << node;
|
||||
// qDebug() << "OSGFileNode::setNode" << node;
|
||||
if (node && optimizeMode != OptimizeMode::None) {
|
||||
// qDebug() << "OSGFileNode::acceptNode - optimize" << node << optimizeMode;
|
||||
osgUtil::Optimizer optimizer;
|
||||
@ -139,18 +146,11 @@ private slots:
|
||||
|
||||
/* 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(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
OSGFileNode::~OSGFileNode()
|
||||
{
|
||||
// qDebug() << "OSGFileNode::~OSGFileNode";
|
||||
delete h;
|
||||
}
|
||||
|
||||
@ -161,7 +161,6 @@ const QUrl OSGFileNode::source() const
|
||||
|
||||
void OSGFileNode::setSource(const QUrl &source)
|
||||
{
|
||||
qDebug() << "OSGFileNode::setSource" << source;
|
||||
if (h->source != source) {
|
||||
h->source = source;
|
||||
setDirty(Source);
|
||||
@ -176,7 +175,6 @@ bool OSGFileNode::async() const
|
||||
|
||||
void OSGFileNode::setAsync(const bool async)
|
||||
{
|
||||
// qDebug() << "OSGFileNode::setAsync" << async;
|
||||
if (h->async != async) {
|
||||
h->async = async;
|
||||
setDirty(Async);
|
||||
@ -191,7 +189,6 @@ OptimizeMode::Enum OSGFileNode::optimizeMode() const
|
||||
|
||||
void OSGFileNode::setOptimizeMode(OptimizeMode::Enum optimizeMode)
|
||||
{
|
||||
// qDebug() << "OSGFileNode::setOptimizeMode" << optimizeMode;
|
||||
if (h->optimizeMode != optimizeMode) {
|
||||
h->optimizeMode = optimizeMode;
|
||||
setDirty(OptimizeMode);
|
||||
@ -199,8 +196,16 @@ void OSGFileNode::setOptimizeMode(OptimizeMode::Enum optimizeMode)
|
||||
}
|
||||
}
|
||||
|
||||
void OSGFileNode::update()
|
||||
osg::Node *OSGFileNode::createNode()
|
||||
{
|
||||
// node is created later
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void OSGFileNode::updateNode()
|
||||
{
|
||||
Inherited::updateNode();
|
||||
|
||||
if (isDirty(Async)) {
|
||||
// do nothing...
|
||||
}
|
||||
@ -208,18 +213,9 @@ void OSGFileNode::update()
|
||||
// TODO: trigger a node update ?
|
||||
}
|
||||
if (isDirty(Source)) {
|
||||
h->updateNode();
|
||||
h->updateSource();
|
||||
}
|
||||
}
|
||||
|
||||
void OSGFileNode::attach(osgViewer::View *view)
|
||||
{
|
||||
update();
|
||||
clearDirty();
|
||||
}
|
||||
|
||||
void OSGFileNode::detach(osgViewer::View *view)
|
||||
{}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGFileNode.moc"
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGFileNode.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -39,6 +39,7 @@ QT_END_NAMESPACE
|
||||
namespace osgQtQuick {
|
||||
class OSGQTQUICK_EXPORT OptimizeMode : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Enum { None, Optimize, OptimizeAndCheck };
|
||||
Q_ENUMS(Enum) // TODO switch to Q_ENUM once on Qt 5.5
|
||||
@ -49,6 +50,8 @@ class OSGQTQUICK_EXPORT OSGFileNode : public OSGNode {
|
||||
Q_PROPERTY(bool async READ async WRITE setAsync NOTIFY asyncChanged)
|
||||
Q_PROPERTY(osgQtQuick::OptimizeMode::Enum optimizeMode READ optimizeMode WRITE setOptimizeMode NOTIFY optimizeModeChanged)
|
||||
|
||||
typedef OSGNode Inherited;
|
||||
|
||||
public:
|
||||
OSGFileNode(QObject *parent = 0);
|
||||
virtual ~OSGFileNode();
|
||||
@ -67,14 +70,13 @@ signals:
|
||||
void asyncChanged(const bool async);
|
||||
void optimizeModeChanged(OptimizeMode::Enum);
|
||||
|
||||
protected:
|
||||
virtual osg::Node *createNode();
|
||||
virtual void updateNode();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *h;
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual void attach(osgViewer::View *view);
|
||||
virtual void detach(osgViewer::View *view);
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGGeoTransformNode.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
#include "OSGGeoTransformNode.hpp"
|
||||
|
||||
#include "../utility.h"
|
||||
#include "utils/utility.h"
|
||||
|
||||
#include <osg/ComputeBoundsVisitor>
|
||||
|
||||
@ -38,6 +38,10 @@
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
// NOTE : these flags should not overlap with OSGGroup flags!!!
|
||||
// TODO : find a better way...
|
||||
enum DirtyFlag { Scene = 1 << 10, Position = 1 << 11, Clamp = 1 << 12 };
|
||||
|
||||
struct OSGGeoTransformNode::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
@ -47,7 +51,6 @@ private:
|
||||
osg::ref_ptr<osgEarth::GeoTransform> transform;
|
||||
|
||||
public:
|
||||
OSGNode *childNode;
|
||||
OSGNode *sceneNode;
|
||||
|
||||
float offset;
|
||||
@ -57,31 +60,14 @@ public:
|
||||
|
||||
QVector3D position;
|
||||
|
||||
Hidden(OSGGeoTransformNode *node) : QObject(node), self(node), childNode(NULL), sceneNode(NULL), offset(-1.0), clampToTerrain(false), intoTerrain(false)
|
||||
Hidden(OSGGeoTransformNode *self) : QObject(self), self(self), sceneNode(NULL), offset(-1.0), clampToTerrain(false), intoTerrain(false)
|
||||
{}
|
||||
|
||||
osg::Node *createNode()
|
||||
{
|
||||
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;
|
||||
return transform;
|
||||
}
|
||||
|
||||
bool acceptSceneNode(OSGNode *node)
|
||||
@ -98,37 +84,15 @@ public:
|
||||
sceneNode = node;
|
||||
|
||||
if (sceneNode) {
|
||||
connect(sceneNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onSceneNodeChanged(osg::Node *)));
|
||||
connect(sceneNode, &OSGNode::nodeChanged, this, &OSGGeoTransformNode::Hidden::onSceneNodeChanged);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
qDebug() << "OSGGeoTransformNode::updateSceneNode" << sceneNode;
|
||||
if (sceneNode && sceneNode->node()) {
|
||||
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
|
||||
if (mapNode) {
|
||||
@ -141,15 +105,20 @@ public:
|
||||
|
||||
void updatePosition()
|
||||
{
|
||||
// qDebug() << "OSGGeoTransformNode::updatePosition" << position;
|
||||
|
||||
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";
|
||||
if (!mapNode) {
|
||||
qWarning() << "OSGGeoTransformNode::updatePosition - scene node does not contain a map node";
|
||||
}
|
||||
} else {
|
||||
qWarning() << "OSGGeoTransformNode::updatePosition - scene node is not valid";
|
||||
}
|
||||
|
||||
// TODO factorize this logic to utility (same logic is found elsewhere)
|
||||
osgEarth::GeoPoint geoPoint;
|
||||
if (mapNode) {
|
||||
geoPoint = osgQtQuick::toGeoPoint(mapNode->getTerrain()->getSRS(), position);
|
||||
@ -160,7 +129,7 @@ public:
|
||||
// get "size" of model
|
||||
// TODO this should be done once only...
|
||||
osg::ComputeBoundsVisitor cbv;
|
||||
childNode->node()->accept(cbv);
|
||||
transform->accept(cbv);
|
||||
const osg::BoundingBox & bbox = cbv.getBoundingBox();
|
||||
offset = bbox.radius();
|
||||
|
||||
@ -168,53 +137,33 @@ public:
|
||||
|
||||
// clamp model to terrain if needed
|
||||
intoTerrain = clampGeoPoint(geoPoint, offset, mapNode);
|
||||
} else if (clampToTerrain) {
|
||||
qWarning() << "OSGGeoTransformNode::onChildNodeChanged - cannot clamp without map node";
|
||||
}
|
||||
|
||||
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
|
||||
updateSceneNode();
|
||||
updatePosition();
|
||||
}
|
||||
};
|
||||
|
||||
/* 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(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
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()
|
||||
OSGNode *OSGGeoTransformNode::sceneNode() const
|
||||
{
|
||||
return h->sceneNode;
|
||||
}
|
||||
@ -260,32 +209,25 @@ void OSGGeoTransformNode::setPosition(QVector3D arg)
|
||||
}
|
||||
}
|
||||
|
||||
void OSGGeoTransformNode::update()
|
||||
osg::Node *OSGGeoTransformNode::createNode()
|
||||
{
|
||||
if (isDirty(Child)) {
|
||||
h->updateTransformNode();
|
||||
}
|
||||
return h->createNode();
|
||||
}
|
||||
|
||||
void OSGGeoTransformNode::updateNode()
|
||||
{
|
||||
Inherited::updateNode();
|
||||
|
||||
if (isDirty(Scene)) {
|
||||
h->updateSceneNode();
|
||||
}
|
||||
if (isDirty(Clamp)) {}
|
||||
if (isDirty(Position)) {
|
||||
if (isDirty(Clamp)) {
|
||||
// do nothing...
|
||||
}
|
||||
if (isDirty(Scene | Clamp | 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"
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGGeoTransformNode.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -29,32 +29,24 @@
|
||||
#define _H_OSGQTQUICK_GEOTRANSFORMNODE_H_
|
||||
|
||||
#include "Export.hpp"
|
||||
#include "OSGNode.hpp"
|
||||
#include "OSGGroup.hpp"
|
||||
|
||||
#include <QVector3D>
|
||||
|
||||
// TODO derive from OSGGroup...
|
||||
namespace osgQtQuick {
|
||||
class OSGQTQUICK_EXPORT OSGGeoTransformNode : public OSGNode {
|
||||
Q_OBJECT
|
||||
// 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)
|
||||
|
||||
class OSGQTQUICK_EXPORT OSGGeoTransformNode : public OSGGroup {
|
||||
Q_OBJECT Q_PROPERTY(osgQtQuick::OSGNode *sceneNode 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 position READ position WRITE setPosition NOTIFY positionChanged)
|
||||
|
||||
typedef OSGGroup Inherited;
|
||||
|
||||
public:
|
||||
OSGGeoTransformNode(QObject *parent = 0);
|
||||
virtual ~OSGGeoTransformNode();
|
||||
|
||||
OSGNode *childNode();
|
||||
void setChildNode(OSGNode *node);
|
||||
|
||||
OSGNode *sceneNode();
|
||||
OSGNode *sceneNode() const;
|
||||
void setSceneNode(OSGNode *node);
|
||||
|
||||
bool clampToTerrain() const;
|
||||
@ -66,23 +58,18 @@ public:
|
||||
void setPosition(QVector3D arg);
|
||||
|
||||
signals:
|
||||
void childNodeChanged(OSGNode *node);
|
||||
|
||||
void sceneNodeChanged(OSGNode *node);
|
||||
|
||||
void clampToTerrainChanged(bool arg);
|
||||
void intoTerrainChanged(bool arg);
|
||||
|
||||
void positionChanged(QVector3D arg);
|
||||
|
||||
protected:
|
||||
virtual osg::Node *createNode();
|
||||
virtual void updateNode();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *h;
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual void attach(osgViewer::View *view);
|
||||
virtual void detach(osgViewer::View *view);
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGGroup.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -39,26 +39,26 @@ struct OSGGroup::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OSGGroup * self;
|
||||
|
||||
osg::ref_ptr<osg::Group> group;
|
||||
OSGGroup * const self;
|
||||
|
||||
QMap<OSGNode *, osg::Node *> cache;
|
||||
|
||||
public:
|
||||
Hidden(OSGGroup *node) : QObject(node), self(node), group(new osg::Group)
|
||||
{
|
||||
group = new osg::Group();
|
||||
self->setNode(group);
|
||||
}
|
||||
|
||||
QList<OSGNode *> children;
|
||||
|
||||
public:
|
||||
Hidden(OSGGroup *self) : QObject(self), self(self)
|
||||
{}
|
||||
|
||||
osg::Node *createNode()
|
||||
{
|
||||
return new osg::Group();
|
||||
}
|
||||
|
||||
void appendChild(OSGNode *childNode)
|
||||
{
|
||||
cache[childNode] = childNode->node();
|
||||
// qDebug() << "OSGGroup::appendChild" << childNode;
|
||||
children.append(childNode);
|
||||
connect(childNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onChildNodeChanged(osg::Node *)), Qt::UniqueConnection);
|
||||
connect(childNode, &OSGNode::nodeChanged, this, &osgQtQuick::OSGGroup::Hidden::onChildNodeChanged, Qt::UniqueConnection);
|
||||
self->setDirty(Children);
|
||||
}
|
||||
|
||||
@ -86,27 +86,39 @@ public:
|
||||
self->setDirty(Children);
|
||||
}
|
||||
|
||||
void updateGroupNode()
|
||||
void updateChildren()
|
||||
{
|
||||
qDebug() << "OSGGroup::updateChildren";
|
||||
|
||||
osg::Group *group = static_cast<osg::Group *>(self->node());
|
||||
if (!group) {
|
||||
qWarning() << "OSGGroup::updateChildren - null group";
|
||||
return;
|
||||
}
|
||||
|
||||
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());
|
||||
// qDebug() << "OSGGroup::updateChildren - child" << childNode;
|
||||
if (childNode->node()) {
|
||||
if (index < group->getNumChildren()) {
|
||||
updated |= group->replaceChild(group->getChild(index), childNode->node());
|
||||
} else {
|
||||
updated |= group->addChild(childNode->node());
|
||||
}
|
||||
cache.insert(childNode, childNode->node());
|
||||
index++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
// removing eventual left overs
|
||||
if (index < group->getNumChildren()) {
|
||||
updated |= group->removeChild(index, group->getNumChildren() - index);
|
||||
}
|
||||
// if (updated) {
|
||||
self->emitNodeChanged();
|
||||
// self->emitNodeChanged();
|
||||
// }
|
||||
}
|
||||
|
||||
@ -141,37 +153,53 @@ public:
|
||||
}
|
||||
|
||||
private slots:
|
||||
void onChildNodeChanged(osg::Node *node)
|
||||
void onChildNodeChanged(osg::Node *child)
|
||||
{
|
||||
qDebug() << "OSGGroup::onChildNodeChanged" << node;
|
||||
OSGNode *obj = qobject_cast<OSGNode *>(sender());
|
||||
if (obj) {
|
||||
osg::Node *cacheNode = cache.value(obj, NULL);
|
||||
if (cacheNode) {
|
||||
group->replaceChild(cacheNode, node);
|
||||
} else {
|
||||
// should not happen...
|
||||
}
|
||||
cache[obj] = node;
|
||||
// emit self->nodeChanged(group.get());
|
||||
// qDebug() << "OSGGroup::onChildNodeChanged" << node;
|
||||
|
||||
osg::Group *group = static_cast<osg::Group *>(self->node());
|
||||
|
||||
if (!group) {
|
||||
qWarning() << "OSGGroup::onChildNodeChanged - null group";
|
||||
return;
|
||||
}
|
||||
|
||||
OSGNode *childNode = qobject_cast<OSGNode *>(sender());
|
||||
// qDebug() << "OSGGroup::onChildNodeChanged - child node" << obj;
|
||||
if (!childNode) {
|
||||
qWarning() << "OSGGroup::onChildNodeChanged - sender is not an OSGNode" << sender();
|
||||
return;
|
||||
}
|
||||
if (childNode->node() != child) {
|
||||
qWarning() << "OSGGroup::onChildNodeChanged - child node is not valid" << childNode;
|
||||
return;
|
||||
}
|
||||
bool updated = false;
|
||||
osg::Node *current = cache.value(childNode, NULL);
|
||||
if (current) {
|
||||
updated |= group->replaceChild(current, child);
|
||||
} else {
|
||||
// should not happen...
|
||||
qWarning() << "OSGGroup::onChildNodeChanged - child node is not a child" << childNode;
|
||||
}
|
||||
cache[childNode] = childNode->node();
|
||||
// if (updated) {
|
||||
// emit self->nodeChanged(group.get());
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
/* class OSGGGroupNode */
|
||||
|
||||
OSGGroup::OSGGroup(QObject *parent) : OSGNode(parent), h(new Hidden(this))
|
||||
{
|
||||
qDebug() << "OSGGroup::OSGGroup";
|
||||
}
|
||||
OSGGroup::OSGGroup(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
OSGGroup::~OSGGroup()
|
||||
{
|
||||
// qDebug() << "OSGGroup::~OSGGroup";
|
||||
delete h;
|
||||
}
|
||||
|
||||
QQmlListProperty<OSGNode> OSGGroup::children()
|
||||
QQmlListProperty<OSGNode> OSGGroup::children() const
|
||||
{
|
||||
return QQmlListProperty<OSGNode>(h, 0,
|
||||
&Hidden::append_child,
|
||||
@ -180,34 +208,17 @@ QQmlListProperty<OSGNode> OSGGroup::children()
|
||||
&Hidden::clear_child);
|
||||
}
|
||||
|
||||
void OSGGroup::update()
|
||||
osg::Node *OSGGroup::createNode()
|
||||
{
|
||||
return h->createNode();
|
||||
}
|
||||
|
||||
void OSGGroup::updateNode()
|
||||
{
|
||||
Inherited::updateNode();
|
||||
|
||||
if (isDirty(Children)) {
|
||||
h->updateGroupNode();
|
||||
}
|
||||
}
|
||||
|
||||
void OSGGroup::attach(osgViewer::View *view)
|
||||
{
|
||||
// qDebug() << "OSGGroup::attach " << view;
|
||||
QListIterator<OSGNode *> i(h->children);
|
||||
while (i.hasNext()) {
|
||||
OSGNode *node = i.next();
|
||||
// qDebug() << "OSGGroup::attach - child" << node;
|
||||
OSGNode::attach(node, view);
|
||||
}
|
||||
update();
|
||||
clearDirty();
|
||||
}
|
||||
|
||||
void OSGGroup::detach(osgViewer::View *view)
|
||||
{
|
||||
// qDebug() << "OSGGroup::detach " << view;
|
||||
QListIterator<OSGNode *> i(h->children);
|
||||
while (i.hasNext()) {
|
||||
OSGNode *node = i.next();
|
||||
// qDebug() << "OSGGroup::detach - child" << node;
|
||||
OSGNode::detach(node, view);
|
||||
h->updateChildren();
|
||||
}
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGGroup.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -39,20 +39,21 @@ class OSGQTQUICK_EXPORT OSGGroup : public OSGNode {
|
||||
|
||||
Q_CLASSINFO("DefaultProperty", "children")
|
||||
|
||||
typedef OSGNode Inherited;
|
||||
|
||||
public:
|
||||
explicit OSGGroup(QObject *parent = 0);
|
||||
virtual ~OSGGroup();
|
||||
|
||||
QQmlListProperty<OSGNode> children();
|
||||
QQmlListProperty<OSGNode> children() const;
|
||||
|
||||
protected:
|
||||
virtual osg::Node *createNode();
|
||||
virtual void updateNode();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *h;
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual void attach(osgViewer::View *view);
|
||||
virtual void detach(osgViewer::View *view);
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
|
128
ground/gcs/src/libs/osgearth/osgQtQuick/OSGImageNode.cpp
Normal file
128
ground/gcs/src/libs/osgearth/osgQtQuick/OSGImageNode.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGImageNode.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @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 "OSGImageNode.hpp"
|
||||
|
||||
#include <osg/Texture2D>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <QUrl>
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
enum DirtyFlag { ImageFile = 1 << 0 };
|
||||
|
||||
struct OSGImageNode::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OSGImageNode * const self;
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> texture;
|
||||
|
||||
public:
|
||||
QUrl url;
|
||||
|
||||
Hidden(OSGImageNode *self) : QObject(self), self(self), url()
|
||||
{}
|
||||
|
||||
osg::Node *createNode()
|
||||
{
|
||||
osg::Drawable *quad = osg::createTexturedQuadGeometry(osg::Vec3(0, 0, 0), osg::Vec3(1, 0, 0), osg::Vec3(0, 1, 0));
|
||||
|
||||
osg::Geode *geode = new osg::Geode;
|
||||
|
||||
geode->addDrawable(quad);
|
||||
|
||||
geode->setStateSet(createState());
|
||||
|
||||
return geode;
|
||||
}
|
||||
|
||||
osg::StateSet *createState()
|
||||
{
|
||||
texture = new osg::Texture2D;
|
||||
|
||||
// create the StateSet to store the texture data
|
||||
osg::StateSet *stateset = new osg::StateSet;
|
||||
|
||||
stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
|
||||
|
||||
return stateset;
|
||||
}
|
||||
|
||||
void updateImageFile()
|
||||
{
|
||||
qDebug() << "OSGImageNode::updateImageFile - reading image file" << url.path();
|
||||
osg::Image *image = osgDB::readImageFile(url.path().toStdString());
|
||||
if (texture.valid()) {
|
||||
texture->setImage(image);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* class OSGImageNode */
|
||||
|
||||
OSGImageNode::OSGImageNode(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
OSGImageNode::~OSGImageNode()
|
||||
{
|
||||
delete h;
|
||||
}
|
||||
|
||||
const QUrl OSGImageNode::imageFile() const
|
||||
{
|
||||
return h->url;
|
||||
}
|
||||
|
||||
void OSGImageNode::setImageFile(const QUrl &url)
|
||||
{
|
||||
if (h->url != url) {
|
||||
h->url = url;
|
||||
setDirty(ImageFile);
|
||||
emit imageFileChanged(url);
|
||||
}
|
||||
}
|
||||
|
||||
osg::Node *OSGImageNode::createNode()
|
||||
{
|
||||
return h->createNode();
|
||||
}
|
||||
|
||||
void OSGImageNode::updateNode()
|
||||
{
|
||||
Inherited::updateNode();
|
||||
|
||||
if (isDirty(ImageFile)) {
|
||||
h->updateImageFile();
|
||||
}
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGImageNode.moc"
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGBackgroundNode.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @file OSGImageNode.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -25,24 +25,23 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _H_OSGQTQUICK_BACKGROUNDNODE_H_
|
||||
#define _H_OSGQTQUICK_BACKGROUNDNODE_H_
|
||||
#ifndef _H_OSGQTQUICK_IMAGENODE_H_
|
||||
#define _H_OSGQTQUICK_IMAGENODE_H_
|
||||
|
||||
#include "Export.hpp"
|
||||
#include "OSGNode.hpp"
|
||||
|
||||
#include <QUrl>
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QUrl;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace osgQtQuick {
|
||||
class OSGQTQUICK_EXPORT OSGBackgroundNode : public OSGNode {
|
||||
class OSGQTQUICK_EXPORT OSGImageNode : public OSGNode {
|
||||
Q_OBJECT Q_PROPERTY(QUrl imageFile READ imageFile WRITE setImageFile NOTIFY imageFileChanged)
|
||||
|
||||
typedef OSGNode Inherited;
|
||||
|
||||
public:
|
||||
OSGBackgroundNode(QObject *parent = 0);
|
||||
virtual ~OSGBackgroundNode();
|
||||
OSGImageNode(QObject *parent = 0);
|
||||
virtual ~OSGImageNode();
|
||||
|
||||
const QUrl imageFile() const;
|
||||
void setImageFile(const QUrl &url);
|
||||
@ -50,15 +49,14 @@ public:
|
||||
signals:
|
||||
void imageFileChanged(const QUrl &url);
|
||||
|
||||
protected:
|
||||
virtual osg::Node *createNode();
|
||||
virtual void updateNode();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *h;
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual void attach(osgViewer::View *view);
|
||||
virtual void detach(osgViewer::View *view);
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#endif // _H_OSGQTQUICK_BACKGROUNDNODE_H_
|
||||
#endif // _H_OSGQTQUICK_IMAGENODE_H_
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGNode.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -27,75 +27,39 @@
|
||||
|
||||
#include "OSGNode.hpp"
|
||||
|
||||
#include "DirtySupport.hpp"
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/NodeVisitor>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
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;
|
||||
};
|
||||
|
||||
struct OSGNode::Hidden : public QObject {
|
||||
struct OSGNode::Hidden : public QObject, public DirtySupport {
|
||||
Q_OBJECT
|
||||
|
||||
friend class OSGNode;
|
||||
|
||||
private:
|
||||
OSGNode *const self;
|
||||
|
||||
osg::ref_ptr<osg::Node> node;
|
||||
|
||||
bool complete;
|
||||
|
||||
public:
|
||||
Hidden(OSGNode *node) : QObject(node), self(node), dirty(0)
|
||||
Hidden(OSGNode *self) : QObject(self), self(self), complete(false) /*, dirty(0)*/
|
||||
{}
|
||||
|
||||
bool isDirty(int mask)
|
||||
osg::Node *nodeToUpdate() const
|
||||
{
|
||||
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);
|
||||
}
|
||||
return self->node();
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
// qDebug() << "OSGNode::update BEGIN";
|
||||
if (dirty) {
|
||||
// qDebug() << "OSGNode::update UPDATE";
|
||||
self->update();
|
||||
}
|
||||
clearDirty();
|
||||
// qDebug() << "OSGNode::update DONE";
|
||||
return self->updateNode();
|
||||
}
|
||||
|
||||
bool acceptNode(osg::Node *aNode)
|
||||
@ -103,43 +67,24 @@ public:
|
||||
if (node == aNode) {
|
||||
return false;
|
||||
}
|
||||
if (node && dirty) {
|
||||
// qDebug() << "OSGNode::acceptNode REMOVE CALLBACK" << node;
|
||||
node->setUpdateCallback(NULL);
|
||||
|
||||
int flags = dirty();
|
||||
if (flags) {
|
||||
clearDirty();
|
||||
}
|
||||
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);
|
||||
if (flags) {
|
||||
setDirty(flags);
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
/* class OSGNode */
|
||||
|
||||
OSGNode::OSGNode(QObject *parent) : QObject(parent), h(new Hidden(this))
|
||||
OSGNode::OSGNode(QObject *parent) : QObject(parent), QQmlParserStatus(), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
OSGNode::~OSGNode()
|
||||
@ -155,16 +100,11 @@ osg::Node *OSGNode::node() const
|
||||
void OSGNode::setNode(osg::Node *node)
|
||||
{
|
||||
if (h->acceptNode(node)) {
|
||||
emit nodeChanged(node);
|
||||
emitNodeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool OSGNode::isDirty()
|
||||
{
|
||||
return h->isDirty(0xFFFFFFFF);
|
||||
}
|
||||
|
||||
bool OSGNode::isDirty(int mask)
|
||||
bool OSGNode::isDirty(int mask) const
|
||||
{
|
||||
return h->isDirty(mask);
|
||||
}
|
||||
@ -179,30 +119,39 @@ void OSGNode::clearDirty()
|
||||
h->clearDirty();
|
||||
}
|
||||
|
||||
void OSGNode::attach(OSGNode *node, osgViewer::View *view)
|
||||
osg::Node *OSGNode::createNode()
|
||||
{
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
node->attach(view);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void OSGNode::detach(OSGNode *node, osgViewer::View *view)
|
||||
void OSGNode::updateNode()
|
||||
{}
|
||||
|
||||
void OSGNode::emitNodeChanged()
|
||||
{
|
||||
if (!node) {
|
||||
return;
|
||||
if (h->complete) {
|
||||
emit nodeChanged(node());
|
||||
}
|
||||
node->detach(view);
|
||||
}
|
||||
|
||||
void OSGNode::update()
|
||||
{}
|
||||
void OSGNode::classBegin()
|
||||
{
|
||||
// qDebug() << "OSGNode::classBegin" << this;
|
||||
|
||||
void OSGNode::attach(osgViewer::View *view)
|
||||
{}
|
||||
setNode(createNode());
|
||||
}
|
||||
|
||||
void OSGNode::detach(osgViewer::View *view)
|
||||
{}
|
||||
void OSGNode::componentComplete()
|
||||
{
|
||||
// qDebug() << "OSGNode::componentComplete" << this;
|
||||
|
||||
updateNode();
|
||||
clearDirty();
|
||||
h->complete = true;
|
||||
if (!h->node.valid()) {
|
||||
qWarning() << "OSGNode::componentComplete - node is not valid!" << this;
|
||||
}
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGNode.moc"
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGNode.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -31,6 +31,7 @@
|
||||
#include "Export.hpp"
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlParserStatus>
|
||||
|
||||
/**
|
||||
* Only update() methods are allowed to update the OSG scenegraph.
|
||||
@ -39,25 +40,19 @@
|
||||
* - 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
|
||||
|
||||
namespace osgViewer {
|
||||
class View;
|
||||
} // namespace osgViewer
|
||||
|
||||
namespace osgQtQuick {
|
||||
class OSGQTQUICK_EXPORT OSGNode : public QObject {
|
||||
class OSGQTQUICK_EXPORT OSGNode : public QObject, public QQmlParserStatus {
|
||||
Q_OBJECT
|
||||
|
||||
friend class OSGViewport;
|
||||
friend class NodeUpdateCallback;
|
||||
Q_INTERFACES(QQmlParserStatus)
|
||||
|
||||
public:
|
||||
explicit OSGNode(QObject *parent = 0);
|
||||
@ -66,31 +61,25 @@ public:
|
||||
osg::Node *node() const;
|
||||
void setNode(osg::Node *node);
|
||||
|
||||
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;
|
||||
|
||||
protected:
|
||||
bool isDirty(int mask = 0xFFFF) const;
|
||||
void setDirty(int mask = 0xFFFF);
|
||||
void clearDirty();
|
||||
|
||||
virtual osg::Node *createNode();
|
||||
virtual void updateNode();
|
||||
|
||||
void emitNodeChanged();
|
||||
|
||||
void classBegin();
|
||||
void componentComplete();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *h;
|
||||
|
||||
virtual void attach(osgViewer::View *view);
|
||||
virtual void detach(osgViewer::View *view);
|
||||
|
||||
virtual void update();
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGShapeNode.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
#include "OSGShapeNode.hpp"
|
||||
|
||||
#include "../shapeutils.h"
|
||||
#include "utils/shapeutils.h"
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/Group>
|
||||
@ -37,19 +37,21 @@
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
enum DirtyFlag { ShapeType = 1 << 0 };
|
||||
|
||||
struct OSGShapeNode::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OSGShapeNode * self;
|
||||
OSGShapeNode * const self;
|
||||
|
||||
public:
|
||||
ShapeType::Enum shapeType;
|
||||
|
||||
Hidden(OSGShapeNode *node) : QObject(node), self(node), shapeType(ShapeType::Sphere)
|
||||
Hidden(OSGShapeNode *self) : QObject(self), self(self), shapeType(ShapeType::Sphere)
|
||||
{}
|
||||
|
||||
void updateNode()
|
||||
void updateShapeType()
|
||||
{
|
||||
osg::Node *node = NULL;
|
||||
|
||||
@ -67,26 +69,19 @@ public:
|
||||
node = ShapeUtils::create3DAxis();
|
||||
break;
|
||||
}
|
||||
// Add the node to the scene
|
||||
self->setNode(node);
|
||||
}
|
||||
};
|
||||
|
||||
/* 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))
|
||||
OSGShapeNode::OSGShapeNode(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{
|
||||
qDebug() << "OSGShapeNode::OSGShapeNode";
|
||||
setShapeType(ShapeType::Sphere);
|
||||
setDirty(ShapeType);
|
||||
}
|
||||
|
||||
OSGShapeNode::~OSGShapeNode()
|
||||
{
|
||||
// qDebug() << "OSGShapeNode::~OSGShapeNode";
|
||||
delete h;
|
||||
}
|
||||
|
||||
@ -99,26 +94,24 @@ void OSGShapeNode::setShapeType(ShapeType::Enum type)
|
||||
{
|
||||
if (h->shapeType != type) {
|
||||
h->shapeType = type;
|
||||
setDirty(Type);
|
||||
setDirty(ShapeType);
|
||||
emit shapeTypeChanged(type);
|
||||
}
|
||||
}
|
||||
|
||||
void OSGShapeNode::update()
|
||||
osg::Node *OSGShapeNode::createNode()
|
||||
{
|
||||
if (isDirty(Type)) {
|
||||
h->updateNode();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void OSGShapeNode::updateNode()
|
||||
{
|
||||
Inherited::updateNode();
|
||||
|
||||
if (isDirty(ShapeType)) {
|
||||
h->updateShapeType();
|
||||
}
|
||||
}
|
||||
|
||||
void OSGShapeNode::attach(osgViewer::View *view)
|
||||
{
|
||||
update();
|
||||
clearDirty();
|
||||
}
|
||||
|
||||
void OSGShapeNode::detach(osgViewer::View *view)
|
||||
{}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGShapeNode.moc"
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGShapeNode.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -42,6 +42,8 @@ public:
|
||||
class OSGQTQUICK_EXPORT OSGShapeNode : public OSGNode {
|
||||
Q_OBJECT Q_PROPERTY(osgQtQuick::ShapeType::Enum shapeType READ shapeType WRITE setShapeType NOTIFY shapeTypeChanged)
|
||||
|
||||
typedef OSGNode Inherited;
|
||||
|
||||
public:
|
||||
OSGShapeNode(QObject *parent = 0);
|
||||
virtual ~OSGShapeNode();
|
||||
@ -52,14 +54,13 @@ public:
|
||||
signals:
|
||||
void shapeTypeChanged(ShapeType::Enum);
|
||||
|
||||
protected:
|
||||
virtual osg::Node *createNode();
|
||||
virtual void updateNode();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *h;
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual void attach(osgViewer::View *view);
|
||||
virtual void detach(osgViewer::View *view);
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGSkyNode.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -27,6 +27,8 @@
|
||||
|
||||
#include "OSGSkyNode.hpp"
|
||||
|
||||
#include "OSGViewport.hpp"
|
||||
|
||||
#include <osgViewer/View>
|
||||
|
||||
#include <osgEarth/Config>
|
||||
@ -39,6 +41,8 @@
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
enum DirtyFlag { Scene = 1 << 0, Viewport = 1 << 1, DateTime = 1 << 2, Light = 1 << 3 };
|
||||
|
||||
struct OSGSkyNode::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
@ -48,13 +52,15 @@ private:
|
||||
osg::ref_ptr<osgEarth::Util::SkyNode> skyNode;
|
||||
|
||||
public:
|
||||
OSGNode *sceneNode;
|
||||
OSGNode *sceneNode;
|
||||
OSGViewport *viewport;
|
||||
|
||||
bool sunLightEnabled;
|
||||
QDateTime dateTime;
|
||||
double minimumAmbientLight;
|
||||
bool sunLightEnabled;
|
||||
QDateTime dateTime;
|
||||
double minimumAmbientLight;
|
||||
|
||||
Hidden(OSGSkyNode *node) : QObject(node), self(node), sceneNode(NULL), sunLightEnabled(true), minimumAmbientLight(0.03)
|
||||
Hidden(OSGSkyNode *self) : QObject(self), self(self), sceneNode(NULL), viewport(NULL),
|
||||
sunLightEnabled(true), minimumAmbientLight(0.03)
|
||||
{
|
||||
dateTime = QDateTime::currentDateTime();
|
||||
}
|
||||
@ -76,27 +82,28 @@ public:
|
||||
sceneNode = node;
|
||||
|
||||
if (sceneNode) {
|
||||
connect(sceneNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onSceneNodeChanged(osg::Node *)));
|
||||
connect(sceneNode, &OSGNode::nodeChanged, this, &OSGSkyNode::Hidden::onSceneNodeChanged);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void updateSkyNode()
|
||||
void updateScene()
|
||||
{
|
||||
if (!sceneNode || !sceneNode->node()) {
|
||||
qWarning() << "OSGSkyNode::acceptNode - scene node not valid";
|
||||
qWarning() << "OSGSkyNode::updateScene - scene node not valid";
|
||||
self->setNode(NULL);
|
||||
return;
|
||||
}
|
||||
qDebug() << "OSGSkyNode::updateScene - scene node" << sceneNode->node();
|
||||
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
|
||||
if (!mapNode) {
|
||||
qWarning() << "OSGSkyNode::acceptNode - scene node does not contain a map node";
|
||||
qWarning() << "OSGSkyNode::updateScene - scene node does not contain a map node";
|
||||
self->setNode(NULL);
|
||||
return;
|
||||
}
|
||||
if (!mapNode->getMap()->isGeocentric()) {
|
||||
qWarning() << "OSGSkyNode::acceptNode - map node is not geocentric";
|
||||
qWarning() << "OSGSkyNode::updateScene - map node is not geocentric";
|
||||
self->setNode(NULL);
|
||||
return;
|
||||
}
|
||||
@ -117,7 +124,7 @@ public:
|
||||
} else {
|
||||
skyNode->removeChild(0, 1);
|
||||
skyNode->addChild(sceneNode->node());
|
||||
self->emitNodeChanged();
|
||||
// self->emitNodeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,8 +149,23 @@ public:
|
||||
}
|
||||
*/
|
||||
|
||||
void updateViewport()
|
||||
{
|
||||
qDebug() << "OSGSkyNode::updateViewport" << skyNode;
|
||||
if (!skyNode.valid()) {
|
||||
qWarning() << "OSGSkyNode::updateViewport - invalid sky node" << skyNode;
|
||||
return;
|
||||
}
|
||||
qDebug() << "OSGSkyNode::updateViewport - attaching to" << viewport->asView();
|
||||
skyNode->attach(viewport->asView());
|
||||
}
|
||||
|
||||
void updateSunLightEnabled()
|
||||
{
|
||||
if (!skyNode.valid()) {
|
||||
qWarning() << "OSGSkyNode::updateSunLightEnabled - invalid sky node";
|
||||
return;
|
||||
}
|
||||
if (!skyNode.valid()) {
|
||||
return;
|
||||
}
|
||||
@ -153,10 +175,11 @@ public:
|
||||
void updateDateTime()
|
||||
{
|
||||
if (!skyNode.valid()) {
|
||||
qWarning() << "OSGSkyNode::updateDateTime - invalid sky node";
|
||||
return;
|
||||
}
|
||||
if (!dateTime.isValid()) {
|
||||
qWarning() << "OSGSkyNode::acceptDateTime - invalid date/time" << dateTime;
|
||||
qWarning() << "OSGSkyNode::updateDateTime - invalid date/time" << dateTime;
|
||||
}
|
||||
|
||||
QDate date = dateTime.date();
|
||||
@ -168,6 +191,7 @@ public:
|
||||
void updateMinimumAmbientLight()
|
||||
{
|
||||
if (!skyNode.valid()) {
|
||||
qWarning() << "OSGSkyNode::updateMinimumAmbientLight - invalid sky node";
|
||||
return;
|
||||
}
|
||||
double d = minimumAmbientLight;
|
||||
@ -193,28 +217,23 @@ private slots:
|
||||
void onSceneNodeChanged(osg::Node *node)
|
||||
{
|
||||
qDebug() << "OSGSkyNode::onSceneNodeChanged" << node;
|
||||
updateSkyNode();
|
||||
updateScene();
|
||||
}
|
||||
};
|
||||
|
||||
/* class OSGSkyNode */
|
||||
|
||||
enum DirtyFlag { Child = 1 << 0, DateTime = 1 << 1, Light = 1 << 2 };
|
||||
|
||||
OSGSkyNode::OSGSkyNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
|
||||
OSGSkyNode::OSGSkyNode(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{
|
||||
qDebug() << "OSGSkyNode::OSGSkyNode";
|
||||
setSunLightEnabled(true);
|
||||
setMinimumAmbientLight(0.03);
|
||||
setDirty(DateTime | Light);
|
||||
}
|
||||
|
||||
OSGSkyNode::~OSGSkyNode()
|
||||
{
|
||||
// qDebug() << "OSGSkyNode::~OSGSkyNode";
|
||||
delete h;
|
||||
}
|
||||
|
||||
OSGNode *OSGSkyNode::sceneNode()
|
||||
OSGNode *OSGSkyNode::sceneNode() const
|
||||
{
|
||||
return h->sceneNode;
|
||||
}
|
||||
@ -222,12 +241,26 @@ OSGNode *OSGSkyNode::sceneNode()
|
||||
void OSGSkyNode::setSceneNode(OSGNode *node)
|
||||
{
|
||||
if (h->acceptSceneNode(node)) {
|
||||
setDirty(Child);
|
||||
setDirty(Scene);
|
||||
emit sceneNodeChanged(node);
|
||||
}
|
||||
}
|
||||
|
||||
bool OSGSkyNode::sunLightEnabled()
|
||||
OSGViewport *OSGSkyNode::viewport() const
|
||||
{
|
||||
return h->viewport;
|
||||
}
|
||||
|
||||
void OSGSkyNode::setViewport(OSGViewport *viewport)
|
||||
{
|
||||
if (h->viewport != viewport) {
|
||||
h->viewport = viewport;
|
||||
setDirty(Viewport);
|
||||
emit viewportChanged(viewport);
|
||||
}
|
||||
}
|
||||
|
||||
bool OSGSkyNode::sunLightEnabled() const
|
||||
{
|
||||
return h->sunLightEnabled;
|
||||
}
|
||||
@ -241,7 +274,7 @@ void OSGSkyNode::setSunLightEnabled(bool enabled)
|
||||
}
|
||||
}
|
||||
|
||||
QDateTime OSGSkyNode::dateTime()
|
||||
QDateTime OSGSkyNode::dateTime() const
|
||||
{
|
||||
return h->dateTime;
|
||||
}
|
||||
@ -255,7 +288,7 @@ void OSGSkyNode::setDateTime(QDateTime dateTime)
|
||||
}
|
||||
}
|
||||
|
||||
double OSGSkyNode::minimumAmbientLight()
|
||||
double OSGSkyNode::minimumAmbientLight() const
|
||||
{
|
||||
return h->minimumAmbientLight;
|
||||
}
|
||||
@ -269,10 +302,20 @@ void OSGSkyNode::setMinimumAmbientLight(double ambient)
|
||||
}
|
||||
}
|
||||
|
||||
void OSGSkyNode::update()
|
||||
osg::Node *OSGSkyNode::createNode()
|
||||
{
|
||||
if (isDirty(Child)) {
|
||||
h->updateSkyNode();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void OSGSkyNode::updateNode()
|
||||
{
|
||||
Inherited::updateNode();
|
||||
|
||||
if (isDirty(Scene)) {
|
||||
h->updateScene();
|
||||
}
|
||||
if (isDirty(Viewport)) {
|
||||
h->updateViewport();
|
||||
}
|
||||
if (isDirty(Light)) {
|
||||
h->updateSunLightEnabled();
|
||||
@ -282,23 +325,6 @@ void OSGSkyNode::update()
|
||||
h->updateDateTime();
|
||||
}
|
||||
}
|
||||
|
||||
void OSGSkyNode::attach(osgViewer::View *view)
|
||||
{
|
||||
// qDebug() << "OSGSkyNode::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);
|
||||
OSGNode::detach(h->sceneNode, view);
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGSkyNode.moc"
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGSkyNode.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -43,45 +43,52 @@ class QUrl;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace osgQtQuick {
|
||||
class OSGQTQUICK_EXPORT OSGSkyNode : public OSGNode {
|
||||
// TODO rename to sceneNode
|
||||
Q_OBJECT Q_PROPERTY(osgQtQuick::OSGNode *sceneData READ sceneNode WRITE setSceneNode NOTIFY sceneNodeChanged)
|
||||
class OSGViewport;
|
||||
|
||||
// TODO should derive from OSGGroup
|
||||
class OSGQTQUICK_EXPORT OSGSkyNode : public OSGNode {
|
||||
Q_OBJECT Q_PROPERTY(osgQtQuick::OSGNode *sceneNode READ sceneNode WRITE setSceneNode NOTIFY sceneNodeChanged)
|
||||
Q_PROPERTY(osgQtQuick::OSGViewport * viewport READ viewport WRITE setViewport NOTIFY viewportChanged)
|
||||
Q_PROPERTY(bool sunLightEnabled READ sunLightEnabled WRITE setSunLightEnabled NOTIFY sunLightEnabledChanged)
|
||||
Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY dateTimeChanged)
|
||||
Q_PROPERTY(double minimumAmbientLight READ minimumAmbientLight WRITE setMinimumAmbientLight NOTIFY minimumAmbientLightChanged)
|
||||
|
||||
typedef OSGNode Inherited;
|
||||
|
||||
public:
|
||||
OSGSkyNode(QObject *parent = 0);
|
||||
virtual ~OSGSkyNode();
|
||||
|
||||
OSGNode *sceneNode();
|
||||
OSGNode *sceneNode() const;
|
||||
void setSceneNode(OSGNode *node);
|
||||
|
||||
bool sunLightEnabled();
|
||||
OSGViewport *viewport() const;
|
||||
void setViewport(OSGViewport *viewport);
|
||||
|
||||
bool sunLightEnabled() const;
|
||||
void setSunLightEnabled(bool arg);
|
||||
|
||||
QDateTime dateTime();
|
||||
QDateTime dateTime() const;
|
||||
void setDateTime(QDateTime arg);
|
||||
|
||||
double minimumAmbientLight();
|
||||
double minimumAmbientLight() const;
|
||||
void setMinimumAmbientLight(double arg);
|
||||
|
||||
signals:
|
||||
void sceneNodeChanged(OSGNode *node);
|
||||
void viewportChanged(OSGViewport *viewport);
|
||||
|
||||
void sunLightEnabledChanged(bool arg);
|
||||
void dateTimeChanged(QDateTime arg);
|
||||
void minimumAmbientLightChanged(double arg);
|
||||
|
||||
protected:
|
||||
virtual osg::Node *createNode();
|
||||
virtual void updateNode();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *h;
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual void attach(osgViewer::View *view);
|
||||
virtual void detach(osgViewer::View *view);
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGTextNode.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
#include "OSGTextNode.hpp"
|
||||
|
||||
#include "../utility.h"
|
||||
#include "utils/utility.h"
|
||||
|
||||
#include <osgText/Text>
|
||||
#include <osg/Geode>
|
||||
@ -37,6 +37,8 @@
|
||||
#include <QColor>
|
||||
|
||||
namespace osgQtQuick {
|
||||
enum DirtyFlag { Text = 1 << 0, Color = 1 << 1 };
|
||||
|
||||
struct OSGTextNode::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
@ -49,24 +51,24 @@ public:
|
||||
QString textString;
|
||||
QColor color;
|
||||
|
||||
Hidden(OSGTextNode *node) : QObject(node), self(node)
|
||||
Hidden(OSGTextNode *self) : QObject(self), self(self)
|
||||
{}
|
||||
|
||||
osg::Node *createNode()
|
||||
{
|
||||
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();
|
||||
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);
|
||||
camera->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
#endif
|
||||
return text;
|
||||
}
|
||||
|
||||
void updateText()
|
||||
@ -88,10 +90,10 @@ public:
|
||||
|
||||
/* class OSGTextNode */
|
||||
|
||||
enum DirtyFlag { Text = 1 << 0, Color = 1 << 1 };
|
||||
|
||||
OSGTextNode::OSGTextNode(QObject *node) : OSGNode(node), h(new Hidden(this))
|
||||
{}
|
||||
OSGTextNode::OSGTextNode(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{
|
||||
setDirty(Text | Color);
|
||||
}
|
||||
|
||||
OSGTextNode::~OSGTextNode()
|
||||
{
|
||||
@ -126,8 +128,15 @@ void OSGTextNode::setColor(const QColor &color)
|
||||
}
|
||||
}
|
||||
|
||||
void OSGTextNode::update()
|
||||
osg::Node *OSGTextNode::createNode()
|
||||
{
|
||||
return h->createNode();
|
||||
}
|
||||
|
||||
void OSGTextNode::updateNode()
|
||||
{
|
||||
Inherited::updateNode();
|
||||
|
||||
if (isDirty(Text)) {
|
||||
h->updateText();
|
||||
}
|
||||
@ -135,15 +144,6 @@ void OSGTextNode::update()
|
||||
h->updateColor();
|
||||
}
|
||||
}
|
||||
|
||||
void OSGTextNode::attach(osgViewer::View *view)
|
||||
{
|
||||
update();
|
||||
clearDirty();
|
||||
}
|
||||
|
||||
void OSGTextNode::detach(osgViewer::View *view)
|
||||
{}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGTextNode.moc"
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGTextNode.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -38,6 +38,8 @@ class OSGQTQUICK_EXPORT OSGTextNode : public OSGNode {
|
||||
Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
|
||||
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
|
||||
|
||||
typedef OSGNode Inherited;
|
||||
|
||||
public:
|
||||
explicit OSGTextNode(QObject *parent = 0);
|
||||
virtual ~OSGTextNode();
|
||||
@ -52,14 +54,13 @@ signals:
|
||||
void textChanged(const QString &text);
|
||||
void colorChanged(const QColor &color);
|
||||
|
||||
protected:
|
||||
virtual osg::Node *createNode();
|
||||
virtual void updateNode();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *h;
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual void attach(osgViewer::View *view);
|
||||
virtual void detach(osgViewer::View *view);
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGTransformNode.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -34,6 +34,10 @@
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
// NOTE : these flags should not overlap with OSGGroup flags!!!
|
||||
// TODO : find a better way...
|
||||
enum DirtyFlag { Scale = 1 << 10, Position = 1 << 11, Attitude = 1 << 12 };
|
||||
|
||||
struct OSGTransformNode::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
@ -43,63 +47,22 @@ private:
|
||||
osg::ref_ptr<osg::PositionAttitudeTransform> transform;
|
||||
|
||||
public:
|
||||
OSGNode *childNode;
|
||||
|
||||
QVector3D scale;
|
||||
QVector3D attitude;
|
||||
QVector3D position;
|
||||
|
||||
Hidden(OSGTransformNode *node) : QObject(node), self(node), childNode(NULL)
|
||||
Hidden(OSGTransformNode *self) : QObject(self), self(self)
|
||||
{}
|
||||
|
||||
osg::Node *createNode()
|
||||
{
|
||||
transform = new osg::PositionAttitudeTransform();
|
||||
self->setNode(transform);
|
||||
}
|
||||
|
||||
bool acceptChildNode(OSGNode *node)
|
||||
{
|
||||
qDebug() << "OSGTransformNode::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;
|
||||
}
|
||||
|
||||
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();
|
||||
// }
|
||||
return transform;
|
||||
}
|
||||
|
||||
void updateScale()
|
||||
{
|
||||
// qDebug() << "OSGTransformNode::updateScale" << scale;
|
||||
if ((scale.x() != 0.0) || (scale.y() != 0.0) || (scale.z() != 0.0)) {
|
||||
transform->setScale(osg::Vec3d(scale.x(), scale.y(), scale.z()));
|
||||
// transform->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
|
||||
@ -118,52 +81,24 @@ public:
|
||||
yaw, osg::Vec3d(0, 0, -1));
|
||||
|
||||
transform->setAttitude(q);
|
||||
|
||||
// position
|
||||
transform->setPosition(osg::Vec3d(position.x(), position.y(), position.z()));
|
||||
}
|
||||
|
||||
void updatePosition()
|
||||
{
|
||||
transform->setPosition(osg::Vec3d(position.x(), position.y(), position.z()));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void onChildNodeChanged(osg::Node *node)
|
||||
{
|
||||
qDebug() << "OSGTransformNode::onChildNodeChanged" << node;
|
||||
updateTransformNode();
|
||||
}
|
||||
};
|
||||
|
||||
/* class OSGTransformNode */
|
||||
|
||||
enum DirtyFlag { Child = 1 << 0, Scale = 1 << 1, Position = 1 << 2, Attitude = 1 << 3 };
|
||||
|
||||
OSGTransformNode::OSGTransformNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
|
||||
{
|
||||
qDebug() << "OSGTransformNode::OSGTransformNode";
|
||||
}
|
||||
OSGTransformNode::OSGTransformNode(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
OSGTransformNode::~OSGTransformNode()
|
||||
{
|
||||
// qDebug() << "OSGTransformNode::~OSGTransformNode";
|
||||
delete h;
|
||||
}
|
||||
|
||||
OSGNode *OSGTransformNode::childNode()
|
||||
{
|
||||
return h->childNode;
|
||||
}
|
||||
|
||||
void OSGTransformNode::setChildNode(OSGNode *node)
|
||||
{
|
||||
if (h->acceptChildNode(node)) {
|
||||
setDirty(Child);
|
||||
emit childNodeChanged(node);
|
||||
}
|
||||
}
|
||||
|
||||
QVector3D OSGTransformNode::scale() const
|
||||
{
|
||||
return h->scale;
|
||||
@ -206,11 +141,15 @@ void OSGTransformNode::setPosition(QVector3D arg)
|
||||
}
|
||||
}
|
||||
|
||||
void OSGTransformNode::update()
|
||||
osg::Node *OSGTransformNode::createNode()
|
||||
{
|
||||
if (isDirty(Child)) {
|
||||
h->updateTransformNode();
|
||||
}
|
||||
return h->createNode();
|
||||
}
|
||||
|
||||
void OSGTransformNode::updateNode()
|
||||
{
|
||||
Inherited::updateNode();
|
||||
|
||||
if (isDirty(Scale)) {
|
||||
h->updateScale();
|
||||
}
|
||||
@ -221,19 +160,6 @@ void OSGTransformNode::update()
|
||||
h->updatePosition();
|
||||
}
|
||||
}
|
||||
|
||||
void OSGTransformNode::attach(osgViewer::View *view)
|
||||
{
|
||||
OSGNode::attach(h->childNode, view);
|
||||
|
||||
update();
|
||||
clearDirty();
|
||||
}
|
||||
|
||||
void OSGTransformNode::detach(osgViewer::View *view)
|
||||
{
|
||||
OSGNode::detach(h->childNode, view);
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGTransformNode.moc"
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGTransformNode.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -29,28 +29,22 @@
|
||||
#define _H_OSGQTQUICK_TRANSFORMNODE_H_
|
||||
|
||||
#include "Export.hpp"
|
||||
#include "OSGNode.hpp"
|
||||
#include "OSGGroup.hpp"
|
||||
|
||||
#include <QVector3D>
|
||||
|
||||
// TODO derive from OSGGroup...
|
||||
namespace osgQtQuick {
|
||||
class OSGQTQUICK_EXPORT OSGTransformNode : public OSGNode {
|
||||
Q_OBJECT
|
||||
// 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)
|
||||
class OSGQTQUICK_EXPORT OSGTransformNode : public OSGGroup {
|
||||
Q_OBJECT Q_PROPERTY(QVector3D scale READ scale WRITE setScale NOTIFY scaleChanged)
|
||||
Q_PROPERTY(QVector3D attitude READ attitude WRITE setAttitude NOTIFY attitudeChanged)
|
||||
Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged)
|
||||
|
||||
typedef OSGGroup Inherited;
|
||||
|
||||
public:
|
||||
OSGTransformNode(QObject *parent = 0);
|
||||
virtual ~OSGTransformNode();
|
||||
|
||||
OSGNode *childNode();
|
||||
void setChildNode(OSGNode *node);
|
||||
|
||||
QVector3D scale() const;
|
||||
void setScale(QVector3D arg);
|
||||
|
||||
@ -61,20 +55,17 @@ public:
|
||||
void setPosition(QVector3D arg);
|
||||
|
||||
signals:
|
||||
void childNodeChanged(OSGNode *node);
|
||||
|
||||
void scaleChanged(QVector3D arg);
|
||||
void attitudeChanged(QVector3D arg);
|
||||
void positionChanged(QVector3D arg);
|
||||
|
||||
protected:
|
||||
virtual osg::Node *createNode();
|
||||
virtual void updateNode();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *h;
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual void attach(osgViewer::View *view);
|
||||
virtual void detach(osgViewer::View *view);
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGViewport.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -27,13 +27,14 @@
|
||||
|
||||
#include "OSGViewport.hpp"
|
||||
|
||||
#include "../osgearth.h"
|
||||
#include "../utility.h"
|
||||
#include "osgearth.h"
|
||||
#include "utils/utility.h"
|
||||
|
||||
#include "OSGNode.hpp"
|
||||
#include "OSGCamera.hpp"
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/DeleteHandler>
|
||||
#include <osg/GLObjects>
|
||||
#include <osg/ApplicationUsage>
|
||||
@ -41,10 +42,7 @@
|
||||
#include <osgViewer/CompositeViewer>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
#include <osgGA/StateSetManipulator>
|
||||
|
||||
#ifdef USE_OSGEARTH
|
||||
#include <osgEarth/MapNode>
|
||||
#endif
|
||||
#include <osgGA/CameraManipulator>
|
||||
|
||||
#include <QOpenGLContext>
|
||||
#include <QQuickWindow>
|
||||
@ -55,10 +53,6 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <QThread>
|
||||
#include <QApplication>
|
||||
|
||||
namespace osgQtQuick {
|
||||
/*
|
||||
Debugging tips
|
||||
- export OSG_NOTIFY_LEVEL=DEBUG
|
||||
@ -79,18 +73,66 @@ namespace osgQtQuick {
|
||||
|
||||
TODO : add OSGView to handle multiple views for a given OSGViewport
|
||||
*/
|
||||
|
||||
/*
|
||||
that's a typical error when working with high-resolution (retina)
|
||||
displays. The issue here is that on the high-resolution devices, the UI
|
||||
operates with a virtual pixel size that is smaller than the real number
|
||||
of pixels on the device. For example, you get coordinates from 0 to 2048
|
||||
while the real device resolution if 4096 pixels. This factor has to be
|
||||
taken into account when mapping from window coordinates to OpenGL, e.g.,
|
||||
when calling glViewport.
|
||||
|
||||
How you can get this factor depends on the GUI library you are using. In
|
||||
Qt, you can query it with QWindow::devicePixelRatio():
|
||||
http://doc.qt.io/qt-5/qwindow.html#devicePixelRatio
|
||||
|
||||
So, there should be something like
|
||||
glViewport(0, 0, window->width() * window->devicePixelRatio(),
|
||||
window->height() * window->devicePixelRatio()).
|
||||
|
||||
Also keep in mind that you have to do the same e.g. for mouse coordinates.
|
||||
|
||||
I think osgQt already handles this correctly, so you shouldn't have to
|
||||
worry about this if you use the classes provided by osgQt ...
|
||||
*/
|
||||
|
||||
namespace osgQtQuick {
|
||||
// enum DirtyFlag { Scene = 1 << 0, Camera = 1 << 1 };
|
||||
|
||||
class ViewportRenderer;
|
||||
|
||||
struct OSGViewport::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
friend ViewportRenderer;
|
||||
|
||||
Hidden(OSGViewport *viewport) : QObject(viewport),
|
||||
self(viewport),
|
||||
window(NULL),
|
||||
sceneData(NULL),
|
||||
camera(NULL),
|
||||
updateMode(UpdateMode::Discrete),
|
||||
frameTimer(-1)
|
||||
private:
|
||||
OSGViewport *const self;
|
||||
|
||||
QQuickWindow *window;
|
||||
|
||||
int frameTimer;
|
||||
|
||||
osg::ref_ptr<osg::GraphicsContext> gc;
|
||||
|
||||
public:
|
||||
OSGNode *sceneNode;
|
||||
OSGCamera *cameraNode;
|
||||
|
||||
osg::ref_ptr<osgViewer::CompositeViewer> viewer;
|
||||
osg::ref_ptr<osgViewer::View> view;
|
||||
|
||||
OSGCameraManipulator *manipulator;
|
||||
|
||||
UpdateMode::Enum updateMode;
|
||||
|
||||
bool busy;
|
||||
|
||||
static QtKeyboardMap keyMap;
|
||||
|
||||
Hidden(OSGViewport *self) : QObject(self), self(self), window(NULL), frameTimer(-1),
|
||||
sceneNode(NULL), cameraNode(NULL), manipulator(NULL), updateMode(UpdateMode::OnDemand), busy(false)
|
||||
{
|
||||
OsgEarth::initialize();
|
||||
|
||||
@ -101,7 +143,9 @@ public:
|
||||
|
||||
~Hidden()
|
||||
{
|
||||
stop();
|
||||
disconnect(self);
|
||||
|
||||
stopTimer();
|
||||
|
||||
destroyViewer();
|
||||
}
|
||||
@ -109,195 +153,140 @@ public:
|
||||
public slots:
|
||||
void onWindowChanged(QQuickWindow *window)
|
||||
{
|
||||
qDebug() << "OSGViewport::onWindowChanged" << window;
|
||||
// qDebug() << "OSGViewport::onWindowChanged" << window;
|
||||
// osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "onWindowChanged");
|
||||
if (window) {
|
||||
// window->setClearBeforeRendering(false);
|
||||
connect(window, &QQuickWindow::sceneGraphInitialized, this, &Hidden::onSceneGraphInitialized, Qt::DirectConnection);
|
||||
connect(window, &QQuickWindow::sceneGraphAboutToStop, this, &Hidden::onSceneGraphAboutToStop, Qt::DirectConnection);
|
||||
connect(window, &QQuickWindow::sceneGraphInvalidated, this, &Hidden::onSceneGraphInvalidated, Qt::DirectConnection);
|
||||
// connect(window, &QQuickWindow::sceneGraphInitialized, this, &Hidden::onSceneGraphInitialized, Qt::DirectConnection);
|
||||
// connect(window, &QQuickWindow::sceneGraphAboutToStop, this, &Hidden::onSceneGraphAboutToStop, Qt::DirectConnection);
|
||||
// connect(window, &QQuickWindow::sceneGraphInvalidated, this, &Hidden::onSceneGraphInvalidated, Qt::DirectConnection);
|
||||
// connect(window, &QQuickWindow::visibleChanged, this, &Hidden::visibleChanged, Qt::DirectConnection);
|
||||
// connect(window, &QQuickWindow::widthChanged, this, &Hidden::widthChanged, Qt::DirectConnection);
|
||||
// connect(window, &QQuickWindow::heightChanged, this, &Hidden::heightChanged, Qt::DirectConnection);
|
||||
} else {
|
||||
if (this->window) {
|
||||
disconnect(this->window);
|
||||
}
|
||||
// if (this->window) {
|
||||
// disconnect(this->window);
|
||||
// }
|
||||
}
|
||||
this->window = window;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
bool acceptSceneData(OSGNode *node)
|
||||
bool acceptSceneNode(OSGNode *node)
|
||||
{
|
||||
qDebug() << "OSGViewport::acceptSceneData" << node;
|
||||
if (sceneData == node) {
|
||||
qDebug() << "OSGViewport::acceptSceneNode" << node;
|
||||
if (sceneNode == node) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sceneData) {
|
||||
disconnect(sceneData);
|
||||
if (sceneNode) {
|
||||
disconnect(sceneNode);
|
||||
}
|
||||
|
||||
sceneData = node;
|
||||
sceneNode = node;
|
||||
|
||||
if (sceneData) {
|
||||
acceptNode(sceneData->node());
|
||||
connect(sceneData, &OSGNode::nodeChanged, this, &Hidden::onNodeChanged);
|
||||
if (sceneNode) {
|
||||
connect(sceneNode, &OSGNode::nodeChanged, this, &Hidden::onSceneNodeChanged);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool acceptNode(osg::Node *node)
|
||||
bool acceptCameraNode(OSGCamera *node)
|
||||
{
|
||||
qDebug() << "OSGViewport::acceptCameraNode" << node;
|
||||
if (cameraNode == node) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cameraNode) {
|
||||
disconnect(cameraNode);
|
||||
}
|
||||
|
||||
cameraNode = node;
|
||||
|
||||
if (cameraNode) {
|
||||
connect(cameraNode, &OSGNode::nodeChanged, this, &Hidden::onCameraNodeChanged);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void attach(osgViewer::View *view)
|
||||
bool acceptManipulator(OSGCameraManipulator *m)
|
||||
{
|
||||
if (!sceneData) {
|
||||
qWarning() << "OSGViewport::attach - invalid scene!";
|
||||
return;
|
||||
}
|
||||
// attach scene
|
||||
attach(view, sceneData->node());
|
||||
// attach camera
|
||||
if (camera) {
|
||||
camera->attach(view);
|
||||
} else {
|
||||
qWarning() << "OSGViewport::attach - no camera!";
|
||||
}
|
||||
}
|
||||
|
||||
void attach(osgViewer::View *view, osg::Node *node)
|
||||
{
|
||||
if (!view) {
|
||||
qWarning() << "OSGViewport::attach - view is null";
|
||||
return;
|
||||
}
|
||||
if (!node) {
|
||||
qWarning() << "OSGViewport::attach - node is null";
|
||||
view->setSceneData(NULL);
|
||||
return;
|
||||
qDebug() << "OSGViewport::acceptManipulator" << manipulator;
|
||||
if (manipulator == m) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_OSGEARTH
|
||||
// TODO map handling should not be done here
|
||||
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(node);
|
||||
if (mapNode) {
|
||||
qDebug() << "OSGViewport::attach - found map node" << mapNode;
|
||||
manipulator = m;
|
||||
|
||||
// remove light to prevent unnecessary state changes in SceneView
|
||||
// scene will get light from sky (works only with latest > 2.7)
|
||||
// view->setLightingMode(osg::View::NO_LIGHT);
|
||||
}
|
||||
#endif
|
||||
|
||||
qDebug() << "OSGViewport::attach - set scene" << node;
|
||||
view->setSceneData(node);
|
||||
}
|
||||
|
||||
void detach(osgViewer::View *view)
|
||||
{
|
||||
// detach camera
|
||||
if (camera) {
|
||||
camera->detach(view);
|
||||
}
|
||||
// detach scene
|
||||
view->setSceneData(NULL);
|
||||
}
|
||||
|
||||
void onSceneGraphInitialized()
|
||||
{
|
||||
qDebug() << "OSGViewport::onSceneGraphInitialized";
|
||||
// osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "onSceneGraphInitialized");
|
||||
}
|
||||
|
||||
void onSceneGraphAboutToStop()
|
||||
{
|
||||
qDebug() << "OSGViewport::onSceneGraphAboutToStop";
|
||||
// osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "onSceneGraphAboutToStop");
|
||||
}
|
||||
|
||||
void onSceneGraphInvalidated()
|
||||
{
|
||||
qDebug() << "OSGViewport::onSceneGraphInvalidated";
|
||||
// osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "onSceneGraphInvalidated");
|
||||
return true;
|
||||
}
|
||||
|
||||
void initializeResources()
|
||||
{
|
||||
qDebug() << "OSGViewport::initializeResources";
|
||||
if (view.valid()) {
|
||||
qWarning() << "OSGViewport::initializeResources - view already created!";
|
||||
if (gc.valid()) {
|
||||
// qWarning() << "OSGViewport::initializeResources - gc already created!";
|
||||
return;
|
||||
}
|
||||
view = createView();
|
||||
viewer->addView(view);
|
||||
self->attach(view.get());
|
||||
start();
|
||||
// qDebug() << "OSGViewport::initializeResources";
|
||||
|
||||
// setup graphics context and camera
|
||||
gc = createGraphicsContext();
|
||||
|
||||
cameraNode->setGraphicsContext(gc);
|
||||
|
||||
// qDebug() << "OSGViewport::initializeResources - camera" << cameraNode->asCamera();
|
||||
view->setCamera(cameraNode->asCamera());
|
||||
|
||||
// qDebug() << "OSGViewport::initializeResources - scene data" << sceneNode->node();
|
||||
view->setSceneData(sceneNode->node());
|
||||
|
||||
if (manipulator) {
|
||||
osgGA::CameraManipulator *m = manipulator->asCameraManipulator();
|
||||
// qDebug() << "OSGViewport::initializeResources - manipulator" << m;
|
||||
|
||||
// Setting the manipulator on the camera will change the manipulator node (used to compute the camera home position)
|
||||
// to the view scene node. So we need to save and restore the manipulator node.
|
||||
osg::Node *node = m->getNode();
|
||||
view->setCameraManipulator(m, false);
|
||||
if (node) {
|
||||
m->setNode(node);
|
||||
}
|
||||
|
||||
view->home();
|
||||
} else {
|
||||
view->setCameraManipulator(NULL, false);
|
||||
}
|
||||
|
||||
installHanders();
|
||||
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void releaseResources()
|
||||
{
|
||||
qDebug() << "OSGViewport::releaseResources";
|
||||
if (!view.valid()) {
|
||||
qWarning() << "OSGViewport::releaseResources - view is not valid!";
|
||||
// qDebug() << "OSGViewport::releaseResources";
|
||||
if (!gc.valid()) {
|
||||
qWarning() << "OSGViewport::releaseResources - gc is not valid!";
|
||||
return;
|
||||
}
|
||||
osg::deleteAllGLObjects(view->getCamera()->getGraphicsContext()->getState()->getContextID());
|
||||
osg::deleteAllGLObjects(gc->getState()->getContextID());
|
||||
// view->getSceneData()->releaseGLObjects(view->getCamera()->getGraphicsContext()->getState());
|
||||
// view->getCamera()->releaseGLObjects(view->getCamera()->getGraphicsContext()->getState());
|
||||
// view->getCamera()->getGraphicsContext()->close();
|
||||
// view->getCamera()->setGraphicsContext(NULL);
|
||||
}
|
||||
|
||||
bool acceptUpdateMode(UpdateMode::Enum mode)
|
||||
{
|
||||
if (updateMode == mode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
updateMode = mode;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool acceptCamera(OSGCamera *camera)
|
||||
{
|
||||
qDebug() << "OSGViewport::acceptCamera" << camera;
|
||||
if (this->camera == camera) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this->camera = camera;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
OSGViewport *self;
|
||||
|
||||
QQuickWindow *window;
|
||||
|
||||
OSGNode *sceneData;
|
||||
OSGCamera *camera;
|
||||
|
||||
UpdateMode::Enum updateMode;
|
||||
|
||||
int frameTimer;
|
||||
|
||||
osg::ref_ptr<osgViewer::CompositeViewer> viewer;
|
||||
osg::ref_ptr<osgViewer::View> view;
|
||||
|
||||
static QtKeyboardMap keyMap;
|
||||
|
||||
private:
|
||||
void createViewer()
|
||||
{
|
||||
if (viewer.valid()) {
|
||||
qWarning() << "OSGViewport::createViewer - viewer is valid";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "OSGViewport::createViewer";
|
||||
// qDebug() << "OSGViewport::createViewer";
|
||||
|
||||
viewer = new osgViewer::CompositeViewer();
|
||||
viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
|
||||
@ -306,6 +295,9 @@ public:
|
||||
// disable the default setting of viewer.done() by pressing Escape.
|
||||
viewer->setKeyEventSetsDone(0);
|
||||
// viewer->setQuitEventSetsDone(false);
|
||||
|
||||
view = createView();
|
||||
viewer->addView(view);
|
||||
}
|
||||
|
||||
void destroyViewer()
|
||||
@ -314,17 +306,25 @@ public:
|
||||
qWarning() << "OSGViewport::destroyViewer - viewer is not valid";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "OSGViewport::destroyViewer";
|
||||
// qDebug() << "OSGViewport::destroyViewer";
|
||||
|
||||
viewer = NULL;
|
||||
}
|
||||
|
||||
osgViewer::View *createView()
|
||||
{
|
||||
qDebug() << "OSGViewport::createView";
|
||||
// qDebug() << "OSGViewport::createView";
|
||||
osgViewer::View *view = new osgViewer::View();
|
||||
|
||||
// TODO expose as Qml properties
|
||||
view->setLightingMode(osgViewer::View::SKY_LIGHT);
|
||||
view->getLight()->setAmbient(osg::Vec4(0.6f, 0.6f, 0.6f, 1.0f));
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
void installHanders()
|
||||
{
|
||||
// TODO will the handlers be destroyed???
|
||||
// add the state manipulator
|
||||
view->addEventHandler(new osgGA::StateSetManipulator(view->getCamera()->getOrCreateStateSet()));
|
||||
@ -350,26 +350,14 @@ public:
|
||||
|
||||
// add the screen capture handler
|
||||
// view->addEventHandler(new osgViewer::ScreenCaptureHandler);
|
||||
|
||||
// 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);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
osg::GraphicsContext *createGraphicsContext()
|
||||
{
|
||||
qDebug() << "OSGViewport::createGraphicsContext";
|
||||
// qDebug() << "OSGViewport::createGraphicsContext";
|
||||
|
||||
osg::GraphicsContext::Traits *traits = getTraits();
|
||||
|
||||
// traitsInfo(*traits);
|
||||
|
||||
traits->pbuffer = true;
|
||||
@ -416,19 +404,19 @@ public:
|
||||
return traits;
|
||||
}
|
||||
|
||||
void start()
|
||||
void startTimer()
|
||||
{
|
||||
if (updateMode == UpdateMode::Discrete && (frameTimer < 0)) {
|
||||
qDebug() << "OSGViewport::start - starting timer";
|
||||
frameTimer = startTimer(33, Qt::PreciseTimer);
|
||||
if ((updateMode != UpdateMode::Continuous) && (frameTimer < 0)) {
|
||||
// qDebug() << "OSGViewport::startTimer - starting timer";
|
||||
frameTimer = QObject::startTimer(33, Qt::PreciseTimer);
|
||||
}
|
||||
}
|
||||
|
||||
void stop()
|
||||
void stopTimer()
|
||||
{
|
||||
if (frameTimer >= 0) {
|
||||
qDebug() << "OSGViewport::stop - killing timer";
|
||||
killTimer(frameTimer);
|
||||
// qDebug() << "OSGViewport::stopTimer - killing timer";
|
||||
QObject::killTimer(frameTimer);
|
||||
frameTimer = -1;
|
||||
}
|
||||
}
|
||||
@ -448,34 +436,38 @@ protected:
|
||||
|
||||
private slots:
|
||||
|
||||
void onNodeChanged(osg::Node *node)
|
||||
void onSceneNodeChanged(osg::Node *node)
|
||||
{
|
||||
qDebug() << "OSGViewport::onNodeChanged" << node;
|
||||
qWarning() << "OSGViewport::onNodeChanged - not implemented";
|
||||
// if (view.valid()) {
|
||||
// acceptNode(node);
|
||||
// }
|
||||
qWarning() << "OSGViewport::onSceneNodeChanged - not implemented";
|
||||
}
|
||||
|
||||
void onCameraNodeChanged(osg::Node *node)
|
||||
{
|
||||
qWarning() << "OSGViewport::onCameraNodeChanged - not implemented";
|
||||
}
|
||||
};
|
||||
|
||||
/* class ViewportRenderer */
|
||||
|
||||
class ViewportRenderer : public QQuickFramebufferObject::Renderer {
|
||||
private:
|
||||
OSGViewport::Hidden *const h;
|
||||
|
||||
int frameCount;
|
||||
bool needToDoFrame;
|
||||
|
||||
public:
|
||||
ViewportRenderer(OSGViewport::Hidden *h) : h(h)
|
||||
ViewportRenderer(OSGViewport::Hidden *h) : h(h), frameCount(0), needToDoFrame(false)
|
||||
{
|
||||
qDebug() << "ViewportRenderer::ViewportRenderer";
|
||||
// qDebug() << "ViewportRenderer::ViewportRenderer";
|
||||
// osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "ViewportRenderer::ViewportRenderer");
|
||||
|
||||
h->initializeResources();
|
||||
|
||||
firstFrame = true;
|
||||
needToDoFrame = false;
|
||||
}
|
||||
|
||||
~ViewportRenderer()
|
||||
{
|
||||
qDebug() << "ViewportRenderer::~ViewportRenderer";
|
||||
// qDebug() << "ViewportRenderer::~ViewportRenderer";
|
||||
// osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "ViewportRenderer::~ViewportRenderer");
|
||||
}
|
||||
|
||||
@ -495,29 +487,71 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstFrame) {
|
||||
// TODO this is not correct : switching workspaces in GCS will destroy and recreate the renderer (and frameCount is thus reset to 0).
|
||||
if (frameCount == 0) {
|
||||
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())) {
|
||||
// we always want to draw the first frame
|
||||
needToDoFrame = (frameCount == 0);
|
||||
|
||||
// if not on-demand then do frame
|
||||
if (h->updateMode != UpdateMode::OnDemand) {
|
||||
needToDoFrame = true;
|
||||
int dpr = h->self->window()->devicePixelRatio();
|
||||
h->view->getCamera()->getGraphicsContext()->resized(0, 0, item->width() * dpr, item->height() * dpr);
|
||||
}
|
||||
|
||||
// check if viewport needs to be resized
|
||||
// a redraw will be requested if necessary
|
||||
osg::Viewport *viewport = h->view->getCamera()->getViewport();
|
||||
int dpr = h->self->window()->devicePixelRatio();
|
||||
int width = item->width() * dpr;
|
||||
int height = item->height() * dpr;
|
||||
if ((viewport->width() != width) || (viewport->height() != height)) {
|
||||
// qDebug() << "*** RESIZE" << frameCount << viewport->width() << "x" << viewport->height() << "->" << width << "x" << height;
|
||||
needToDoFrame = true;
|
||||
|
||||
// h->view->getCamera()->resize(width, height);
|
||||
h->view->getCamera()->getGraphicsContext()->resized(0, 0, width, height);
|
||||
|
||||
// trick to force a "home" on first few frames to absorb initial spurious resizes
|
||||
if (frameCount <= 2) {
|
||||
h->view->home();
|
||||
}
|
||||
}
|
||||
|
||||
// refresh busy state
|
||||
// TODO state becomes busy when scene is loading or downloading tiles (should do it only for download)
|
||||
h->self->setBusy(h->view->getDatabasePager()->getRequestsInProgress());
|
||||
// TODO also expose request list size to Qml
|
||||
if (h->view->getDatabasePager()->getFileRequestListSize() > 0) {
|
||||
// qDebug() << h->view->getDatabasePager()->getFileRequestListSize();
|
||||
}
|
||||
|
||||
if (!needToDoFrame) {
|
||||
needToDoFrame = h->viewer->checkNeedToDoFrame();
|
||||
}
|
||||
// workarounds to osg issues
|
||||
if (!needToDoFrame) {
|
||||
// issue 1 : if only root node has an update callback checkNeedToDoFrame should return true but does not
|
||||
// a fix will be submitted to osg (current version is 3.5.1)
|
||||
if (h->view->getSceneData()) {
|
||||
needToDoFrame |= !(h->view->getSceneData()->getUpdateCallback() == NULL);
|
||||
}
|
||||
}
|
||||
if (!needToDoFrame) {
|
||||
// issue 2 : UI events don't trigger a redraw
|
||||
// this issue should be fixed here...
|
||||
// event handling needs a lot of attention :
|
||||
// - sometimes the scene is redrawing continuously (after a drag for example, and single click will stop continuous redraw)
|
||||
// - some events (simple click for instance) trigger a redraw when not needed
|
||||
// - in Earth View : continuous zoom (triggered by holding right button and moving mouse up/down) sometimes stops working when holding mouse still after initiating
|
||||
needToDoFrame = !h->view->getEventQueue()->empty();
|
||||
}
|
||||
if (needToDoFrame) {
|
||||
// qDebug() << "ViewportRenderer::synchronize - update scene" << frameCount;
|
||||
h->viewer->advance();
|
||||
h->viewer->eventTraversal();
|
||||
h->viewer->updateTraversal();
|
||||
@ -537,6 +571,8 @@ public:
|
||||
}
|
||||
|
||||
if (needToDoFrame) {
|
||||
// qDebug() << "ViewportRenderer::render - render scene" << frameCount;
|
||||
|
||||
// needed to properly render models without terrain (Qt bug?)
|
||||
QOpenGLContext::currentContext()->functions()->glUseProgram(0);
|
||||
h->viewer->renderingTraversals();
|
||||
@ -547,6 +583,8 @@ public:
|
||||
// trigger next update
|
||||
update();
|
||||
}
|
||||
|
||||
++frameCount;
|
||||
}
|
||||
|
||||
QOpenGLFramebufferObject *createFramebufferObject(const QSize &size)
|
||||
@ -556,30 +594,18 @@ public:
|
||||
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
|
||||
// format.setSamples(4);
|
||||
|
||||
// Keeping this for reference :
|
||||
// Mac need(ed) to have devicePixelRatio (dpr) taken into account (i.e. dpr = 2).
|
||||
// Further tests on Mac have shown that although dpr is still 2 it should not be used to scale the fbo.
|
||||
// Note that getting the window to get the devicePixelRatio is not great (messing with windows is often a bad idea...)
|
||||
int dpr = 1; // h->self->window()->devicePixelRatio();
|
||||
QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(size.width() / dpr, size.height() / dpr, format);
|
||||
QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(size.width(), size.height(), format);
|
||||
|
||||
return fbo;
|
||||
}
|
||||
|
||||
private:
|
||||
OSGViewport::Hidden *h;
|
||||
|
||||
bool firstFrame;
|
||||
bool needToDoFrame;
|
||||
};
|
||||
|
||||
QtKeyboardMap OSGViewport::Hidden::keyMap = QtKeyboardMap();
|
||||
|
||||
/* class OSGViewport */
|
||||
|
||||
OSGViewport::OSGViewport(QQuickItem *parent) : QQuickFramebufferObject(parent), h(new Hidden(this))
|
||||
OSGViewport::OSGViewport(QQuickItem *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{
|
||||
qDebug() << "OSGViewport::OSGViewport";
|
||||
// setClearBeforeRendering(false);
|
||||
setMirrorVertically(true);
|
||||
setAcceptHoverEvents(true);
|
||||
@ -588,10 +614,48 @@ OSGViewport::OSGViewport(QQuickItem *parent) : QQuickFramebufferObject(parent),
|
||||
|
||||
OSGViewport::~OSGViewport()
|
||||
{
|
||||
qDebug() << "OSGViewport::~OSGViewport";
|
||||
delete h;
|
||||
}
|
||||
|
||||
OSGNode *OSGViewport::sceneNode() const
|
||||
{
|
||||
return h->sceneNode;
|
||||
}
|
||||
|
||||
void OSGViewport::setSceneNode(OSGNode *node)
|
||||
{
|
||||
if (h->acceptSceneNode(node)) {
|
||||
// setDirty(Scene);
|
||||
emit sceneNodeChanged(node);
|
||||
}
|
||||
}
|
||||
|
||||
OSGCamera *OSGViewport::cameraNode() const
|
||||
{
|
||||
return h->cameraNode;
|
||||
}
|
||||
|
||||
void OSGViewport::setCameraNode(OSGCamera *node)
|
||||
{
|
||||
if (h->acceptCameraNode(node)) {
|
||||
// setDirty(Camera);
|
||||
emit cameraNodeChanged(node);
|
||||
}
|
||||
}
|
||||
|
||||
OSGCameraManipulator *OSGViewport::manipulator() const
|
||||
{
|
||||
return h->manipulator;
|
||||
}
|
||||
|
||||
void OSGViewport::setManipulator(OSGCameraManipulator *manipulator)
|
||||
{
|
||||
if (h->acceptManipulator(manipulator)) {
|
||||
// setDirty(Manipulator);
|
||||
emit manipulatorChanged(manipulator);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateMode::Enum OSGViewport::updateMode() const
|
||||
{
|
||||
return h->updateMode;
|
||||
@ -599,95 +663,54 @@ UpdateMode::Enum OSGViewport::updateMode() const
|
||||
|
||||
void OSGViewport::setUpdateMode(UpdateMode::Enum mode)
|
||||
{
|
||||
if (h->acceptUpdateMode(mode)) {
|
||||
emit updateModeChanged(updateMode());
|
||||
if (h->updateMode != mode) {
|
||||
h->updateMode = mode;
|
||||
emit updateModeChanged(mode);
|
||||
}
|
||||
}
|
||||
|
||||
QColor OSGViewport::color() const
|
||||
bool OSGViewport::busy() const
|
||||
{
|
||||
const osg::Vec4 osgColor = h->view->getCamera()->getClearColor();
|
||||
|
||||
return QColor::fromRgbF(osgColor.r(), osgColor.g(), osgColor.b(), osgColor.a());
|
||||
return h->busy;
|
||||
}
|
||||
|
||||
void OSGViewport::setColor(const QColor &color)
|
||||
void OSGViewport::setBusy(const bool busy)
|
||||
{
|
||||
osg::Vec4 osgColor(color.redF(), color.greenF(), color.blueF(), color.alphaF());
|
||||
|
||||
if (h->view->getCamera()->getClearColor() != osgColor) {
|
||||
h->view->getCamera()->setClearColor(osgColor);
|
||||
emit colorChanged(color);
|
||||
if (h->busy != busy) {
|
||||
h->busy = busy;
|
||||
emit busyChanged(busy);
|
||||
}
|
||||
}
|
||||
|
||||
OSGNode *OSGViewport::sceneData()
|
||||
osgViewer::View *OSGViewport::asView() const
|
||||
{
|
||||
return h->sceneData;
|
||||
}
|
||||
|
||||
void OSGViewport::setSceneData(OSGNode *node)
|
||||
{
|
||||
if (h->acceptSceneData(node)) {
|
||||
emit sceneDataChanged(node);
|
||||
}
|
||||
}
|
||||
|
||||
OSGCamera *OSGViewport::camera()
|
||||
{
|
||||
return h->camera;
|
||||
}
|
||||
|
||||
void OSGViewport::setCamera(OSGCamera *camera)
|
||||
{
|
||||
if (h->acceptCamera(camera)) {
|
||||
emit cameraChanged(camera);
|
||||
}
|
||||
return h->view;
|
||||
}
|
||||
|
||||
QQuickFramebufferObject::Renderer *OSGViewport::createRenderer() const
|
||||
{
|
||||
qDebug() << "OSGViewport::createRenderer";
|
||||
// qDebug() << "OSGViewport::createRenderer";
|
||||
// osgQtQuick::openGLContextInfo(QOpenGLContext::currentContext(), "createRenderer");
|
||||
return new ViewportRenderer(h);
|
||||
}
|
||||
|
||||
void OSGViewport::attach(osgViewer::View *view)
|
||||
{
|
||||
// qDebug() << "OSGViewport::attach" << view;
|
||||
if (h->sceneData) {
|
||||
h->sceneData->attach(view);
|
||||
}
|
||||
h->attach(view);
|
||||
}
|
||||
|
||||
void OSGViewport::detach(osgViewer::View *view)
|
||||
{
|
||||
qDebug() << "OSGViewport::detach" << view;
|
||||
h->detach(view);
|
||||
if (h->sceneData) {
|
||||
h->sceneData->detach(view);
|
||||
}
|
||||
}
|
||||
|
||||
void OSGViewport::releaseResources()
|
||||
{
|
||||
QQuickFramebufferObject::releaseResources();
|
||||
// qDebug() << "OSGViewport::releaseResources" << this;
|
||||
Inherited::releaseResources();
|
||||
}
|
||||
|
||||
// see https://bugreports.qt-project.org/browse/QTBUG-41073
|
||||
QSGNode *OSGViewport::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *nodeData)
|
||||
void OSGViewport::classBegin()
|
||||
{
|
||||
// qDebug() << "OSGViewport::updatePaintNode";
|
||||
if (!node) {
|
||||
qDebug() << "OSGViewport::updatePaintNode - set transform";
|
||||
node = QQuickFramebufferObject::updatePaintNode(node, nodeData);
|
||||
QSGSimpleTextureNode *n = static_cast<QSGSimpleTextureNode *>(node);
|
||||
return node;
|
||||
}
|
||||
return QQuickFramebufferObject::updatePaintNode(node, nodeData);
|
||||
// qDebug() << "OSGViewport::classBegin" << this;
|
||||
Inherited::classBegin();
|
||||
}
|
||||
|
||||
void OSGViewport::componentComplete()
|
||||
{
|
||||
// qDebug() << "OSGViewport::componentComplete" << this;
|
||||
Inherited::componentComplete();
|
||||
}
|
||||
|
||||
QPointF OSGViewport::mousePoint(QMouseEvent *event)
|
||||
{
|
||||
@ -785,7 +808,7 @@ void OSGViewport::keyPressEvent(QKeyEvent *event)
|
||||
// among others, it closes popup windows on ESC and forwards the event to the parent widgets
|
||||
// TODO implement
|
||||
// if( _forwardKeyEvents )
|
||||
// inherited::keyPressEvent( event );
|
||||
// Inherited::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void OSGViewport::keyReleaseEvent(QKeyEvent *event)
|
||||
@ -804,7 +827,7 @@ void OSGViewport::keyReleaseEvent(QKeyEvent *event)
|
||||
// among others, it closes popup windows on ESC and forwards the event to the parent widgets
|
||||
// TODO implement
|
||||
// if( _forwardKeyEvents )
|
||||
// inherited::keyReleaseEvent( event );
|
||||
// Inherited::keyReleaseEvent(event);
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGViewport.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -30,6 +30,8 @@
|
||||
|
||||
#include "Export.hpp"
|
||||
|
||||
#include "ga/OSGCameraManipulator.hpp"
|
||||
|
||||
#include <QQuickFramebufferObject>
|
||||
|
||||
namespace osgViewer {
|
||||
@ -49,39 +51,49 @@ public:
|
||||
};
|
||||
|
||||
class OSGQTQUICK_EXPORT OSGViewport : public QQuickFramebufferObject {
|
||||
Q_OBJECT Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
|
||||
Q_OBJECT Q_PROPERTY(osgQtQuick::OSGNode *sceneNode READ sceneNode WRITE setSceneNode NOTIFY sceneNodeChanged)
|
||||
Q_PROPERTY(osgQtQuick::OSGCamera * camera READ cameraNode WRITE setCameraNode NOTIFY cameraNodeChanged)
|
||||
Q_PROPERTY(osgQtQuick::OSGCameraManipulator * manipulator READ manipulator WRITE setManipulator NOTIFY manipulatorChanged)
|
||||
Q_PROPERTY(osgQtQuick::UpdateMode::Enum updateMode READ updateMode WRITE setUpdateMode NOTIFY updateModeChanged)
|
||||
Q_PROPERTY(osgQtQuick::OSGNode * sceneData READ sceneData WRITE setSceneData NOTIFY sceneDataChanged)
|
||||
Q_PROPERTY(osgQtQuick::OSGCamera * camera READ camera WRITE setCamera NOTIFY cameraChanged)
|
||||
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
||||
|
||||
typedef QQuickFramebufferObject Inherited;
|
||||
|
||||
public:
|
||||
friend class ViewportRenderer;
|
||||
|
||||
public:
|
||||
explicit OSGViewport(QQuickItem *parent = 0);
|
||||
virtual ~OSGViewport();
|
||||
|
||||
OSGNode *sceneNode() const;
|
||||
void setSceneNode(OSGNode *node);
|
||||
|
||||
OSGCamera *cameraNode() const;
|
||||
void setCameraNode(OSGCamera *node);
|
||||
|
||||
OSGCameraManipulator *manipulator() const;
|
||||
void setManipulator(OSGCameraManipulator *manipulator);
|
||||
|
||||
UpdateMode::Enum updateMode() const;
|
||||
void setUpdateMode(UpdateMode::Enum mode);
|
||||
|
||||
QColor color() const;
|
||||
void setColor(const QColor &color);
|
||||
|
||||
OSGNode *sceneData();
|
||||
void setSceneData(OSGNode *node);
|
||||
|
||||
OSGCamera *camera();
|
||||
void setCamera(OSGCamera *camera);
|
||||
bool busy() const;
|
||||
void setBusy(const bool busy);
|
||||
|
||||
Renderer *createRenderer() const;
|
||||
void releaseResources();
|
||||
|
||||
osgViewer::View *asView() const;
|
||||
|
||||
signals:
|
||||
void sceneNodeChanged(OSGNode *node);
|
||||
void cameraNodeChanged(OSGCamera *node);
|
||||
void manipulatorChanged(OSGCameraManipulator *manipulator);
|
||||
void updateModeChanged(UpdateMode::Enum mode);
|
||||
void colorChanged(const QColor &color);
|
||||
void sceneDataChanged(OSGNode *node);
|
||||
void cameraChanged(OSGCamera *camera);
|
||||
void busyChanged(bool busy);
|
||||
|
||||
protected:
|
||||
// QQuickItem
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
void mouseReleaseEvent(QMouseEvent *event);
|
||||
@ -92,14 +104,13 @@ protected:
|
||||
void setKeyboardModifiers(QInputEvent *event);
|
||||
QPointF mousePoint(QMouseEvent *event);
|
||||
|
||||
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
|
||||
|
||||
void attach(osgViewer::View *view);
|
||||
void detach(osgViewer::View *view);
|
||||
// QQmlParserStatus
|
||||
void classBegin();
|
||||
void componentComplete();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *h;
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
|
@ -0,0 +1,181 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGCameraManipulator.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @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 "OSGCameraManipulator.hpp"
|
||||
|
||||
#include "../DirtySupport.hpp"
|
||||
#include "../OSGNode.hpp"
|
||||
|
||||
#include <osgGA/CameraManipulator>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
enum DirtyFlag { Scene = 1 << 0 };
|
||||
|
||||
struct OSGCameraManipulator::Hidden : public QObject, public DirtySupport {
|
||||
Q_OBJECT
|
||||
|
||||
friend class OSGCameraManipulator;
|
||||
|
||||
private:
|
||||
OSGCameraManipulator *const self;
|
||||
|
||||
public:
|
||||
osg::ref_ptr<osgGA::CameraManipulator> manipulator;
|
||||
|
||||
OSGNode *sceneNode;
|
||||
|
||||
public:
|
||||
Hidden(OSGCameraManipulator *self) : QObject(self), self(self), sceneNode(NULL)
|
||||
{}
|
||||
|
||||
~Hidden()
|
||||
{}
|
||||
|
||||
osg::Node *nodeToUpdate() const
|
||||
{
|
||||
return manipulator->getNode();
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
return self->update();
|
||||
}
|
||||
|
||||
bool acceptSceneNode(OSGNode *node)
|
||||
{
|
||||
qDebug() << "OSGCameraManipulator::acceptSceneNode" << node;
|
||||
if (sceneNode == node) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sceneNode) {
|
||||
disconnect(sceneNode);
|
||||
}
|
||||
|
||||
sceneNode = node;
|
||||
|
||||
if (sceneNode) {
|
||||
connect(sceneNode, &OSGNode::nodeChanged, this, &OSGCameraManipulator::Hidden::onSceneNodeChanged);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void updateSceneNode()
|
||||
{
|
||||
if (!sceneNode) {
|
||||
qWarning() << "OSGCameraManipulator::updateSceneNode - no scene node";
|
||||
return;
|
||||
}
|
||||
qDebug() << "OSGCameraManipulator::updateSceneNode" << sceneNode;
|
||||
manipulator->setNode(sceneNode->node());
|
||||
}
|
||||
|
||||
private slots:
|
||||
void onSceneNodeChanged(osg::Node *node)
|
||||
{
|
||||
qDebug() << "OSGCameraManipulator::onSceneNodeChanged" << node;
|
||||
updateSceneNode();
|
||||
}
|
||||
};
|
||||
|
||||
/* class OSGCameraManipulator */
|
||||
|
||||
OSGCameraManipulator::OSGCameraManipulator(QObject *parent) : QObject(parent), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
OSGCameraManipulator::~OSGCameraManipulator()
|
||||
{
|
||||
delete h;
|
||||
}
|
||||
|
||||
OSGNode *OSGCameraManipulator::sceneNode() const
|
||||
{
|
||||
return h->sceneNode;
|
||||
}
|
||||
|
||||
void OSGCameraManipulator::setSceneNode(OSGNode *node)
|
||||
{
|
||||
if (h->acceptSceneNode(node)) {
|
||||
setDirty(Scene);
|
||||
emit sceneNodeChanged(node);
|
||||
}
|
||||
}
|
||||
|
||||
bool OSGCameraManipulator::isDirty(int mask) const
|
||||
{
|
||||
return h->isDirty(mask);
|
||||
}
|
||||
|
||||
void OSGCameraManipulator::setDirty(int mask)
|
||||
{
|
||||
h->setDirty(mask);
|
||||
}
|
||||
|
||||
void OSGCameraManipulator::clearDirty()
|
||||
{
|
||||
h->clearDirty();
|
||||
}
|
||||
|
||||
void OSGCameraManipulator::classBegin()
|
||||
{
|
||||
// qDebug() << "OSGCameraManipulator::classBegin" << this;
|
||||
}
|
||||
|
||||
void OSGCameraManipulator::componentComplete()
|
||||
{
|
||||
qDebug() << "OSGCameraManipulator::componentComplete" << this;
|
||||
update();
|
||||
clearDirty();
|
||||
}
|
||||
|
||||
osgGA::CameraManipulator *OSGCameraManipulator::manipulator() const
|
||||
{
|
||||
return h->manipulator;
|
||||
}
|
||||
|
||||
void OSGCameraManipulator::setManipulator(osgGA::CameraManipulator *manipulator)
|
||||
{
|
||||
h->manipulator = manipulator;
|
||||
}
|
||||
|
||||
osgGA::CameraManipulator *OSGCameraManipulator::asCameraManipulator() const
|
||||
{
|
||||
return h->manipulator;
|
||||
}
|
||||
|
||||
void OSGCameraManipulator::update()
|
||||
{
|
||||
if (isDirty(Scene)) {
|
||||
h->updateSceneNode();
|
||||
}
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGCameraManipulator.moc"
|
@ -0,0 +1,81 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGCameraManipulator.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @brief
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _H_OSGQTQUICK_OSGCAMERAMANIPULATOR_H_
|
||||
#define _H_OSGQTQUICK_OSGCAMERAMANIPULATOR_H_
|
||||
|
||||
#include "../Export.hpp"
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlParserStatus>
|
||||
|
||||
namespace osgGA {
|
||||
class CameraManipulator;
|
||||
}
|
||||
|
||||
namespace osgQtQuick {
|
||||
class OSGNode;
|
||||
|
||||
class OSGQTQUICK_EXPORT OSGCameraManipulator : public QObject, public QQmlParserStatus {
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QQmlParserStatus)
|
||||
|
||||
Q_PROPERTY(osgQtQuick::OSGNode * sceneNode READ sceneNode WRITE setSceneNode NOTIFY sceneNodeChanged)
|
||||
|
||||
public:
|
||||
explicit OSGCameraManipulator(QObject *parent = 0);
|
||||
virtual ~OSGCameraManipulator();
|
||||
|
||||
osgGA::CameraManipulator *asCameraManipulator() const;
|
||||
|
||||
OSGNode *sceneNode() const;
|
||||
void setSceneNode(OSGNode *node);
|
||||
|
||||
signals:
|
||||
void sceneNodeChanged(OSGNode *node);
|
||||
|
||||
protected:
|
||||
bool isDirty(int mask = 0xFFFF) const;
|
||||
void setDirty(int mask = 0xFFFF);
|
||||
void clearDirty();
|
||||
|
||||
void classBegin();
|
||||
void componentComplete();
|
||||
|
||||
osgGA::CameraManipulator *manipulator() const;
|
||||
void setManipulator(osgGA::CameraManipulator *manipulator);
|
||||
|
||||
protected:
|
||||
virtual void update();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#endif // _H_OSGQTQUICK_OSGCAMERAMANIPULATOR_H_
|
@ -0,0 +1,69 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGEarthManipulator.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @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 "OSGEarthManipulator.hpp"
|
||||
|
||||
#include "../OSGNode.hpp"
|
||||
|
||||
#include <osgEarthUtil/EarthManipulator>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
struct OSGEarthManipulator::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OSGEarthManipulator * const self;
|
||||
|
||||
public:
|
||||
osg::ref_ptr<osgEarth::Util::EarthManipulator> manipulator;
|
||||
|
||||
Hidden(OSGEarthManipulator *self) : QObject(self), self(self)
|
||||
{
|
||||
manipulator = new osgEarth::Util::EarthManipulator(
|
||||
/*osgGA::StandardManipulator::COMPUTE_HOME_USING_BBOX | osgGA::StandardManipulator::DEFAULT_SETTINGS*/);
|
||||
manipulator->getSettings()->setThrowingEnabled(true);
|
||||
self->setManipulator(manipulator);
|
||||
}
|
||||
|
||||
~Hidden()
|
||||
{}
|
||||
};
|
||||
|
||||
/* class OSGEarthManipulator */
|
||||
|
||||
OSGEarthManipulator::OSGEarthManipulator(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
OSGEarthManipulator::~OSGEarthManipulator()
|
||||
{
|
||||
delete h;
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGEarthManipulator.moc"
|
@ -0,0 +1,52 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGEarthManipulator.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @brief
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _H_OSGQTQUICK_OSGEARTHMANIPULATOR_H_
|
||||
#define _H_OSGQTQUICK_OSGEARTHMANIPULATOR_H_
|
||||
|
||||
#include "../Export.hpp"
|
||||
#include "OSGCameraManipulator.hpp"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace osgQtQuick {
|
||||
class OSGQTQUICK_EXPORT OSGEarthManipulator : public OSGCameraManipulator {
|
||||
Q_OBJECT
|
||||
|
||||
typedef OSGCameraManipulator Inherited;
|
||||
|
||||
public:
|
||||
explicit OSGEarthManipulator(QObject *parent = 0);
|
||||
virtual ~OSGEarthManipulator();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#endif // _H_OSGQTQUICK_OSGEARTHMANIPULATOR_H_
|
@ -0,0 +1,285 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGGeoTransformManipulator.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @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 "OSGGeoTransformManipulator.hpp"
|
||||
|
||||
#include "../OSGNode.hpp"
|
||||
#include "utils/utility.h"
|
||||
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Node>
|
||||
#include <osg/Vec3d>
|
||||
|
||||
#include <osgGA/CameraManipulator>
|
||||
|
||||
#include <osgEarth/GeoData>
|
||||
#include <osgEarth/MapNode>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
enum DirtyFlag { Position = 1 << 10, Attitude = 1 << 11, Clamp = 1 << 12 };
|
||||
|
||||
class MyManipulator : public osgGA::CameraManipulator {
|
||||
public:
|
||||
MyManipulator()
|
||||
{}
|
||||
|
||||
virtual void updateCamera(osg::Camera &camera);
|
||||
|
||||
virtual const char *className() const
|
||||
{
|
||||
return "MyManipulator";
|
||||
}
|
||||
|
||||
virtual void setByMatrix(const osg::Matrixd &matrix)
|
||||
{
|
||||
this->matrix = matrix;
|
||||
}
|
||||
|
||||
virtual void setByInverseMatrix(const osg::Matrixd &matrix)
|
||||
{
|
||||
this->invMatrix = matrix;
|
||||
}
|
||||
|
||||
virtual osg::Matrixd getMatrix() const
|
||||
{
|
||||
return matrix;
|
||||
}
|
||||
|
||||
virtual osg::Matrixd getInverseMatrix() const
|
||||
{
|
||||
return invMatrix;
|
||||
}
|
||||
|
||||
virtual void setNode(osg::Node *node)
|
||||
{
|
||||
this->node = node;
|
||||
}
|
||||
|
||||
virtual const osg::Node *getNode() const
|
||||
{
|
||||
return node.get();
|
||||
}
|
||||
|
||||
virtual osg::Node *getNode()
|
||||
{
|
||||
return node.get();
|
||||
}
|
||||
|
||||
private:
|
||||
osg::Matrixd matrix;
|
||||
osg::Matrixd invMatrix;
|
||||
osg::ref_ptr<osg::Node> node;
|
||||
};
|
||||
|
||||
struct OSGGeoTransformManipulator::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OSGGeoTransformManipulator * const self;
|
||||
|
||||
osg::Matrix cameraPosition;
|
||||
osg::Matrix cameraRotation;
|
||||
|
||||
public:
|
||||
osg::ref_ptr<MyManipulator> manipulator;
|
||||
|
||||
QVector3D attitude;
|
||||
QVector3D position;
|
||||
|
||||
bool clampToTerrain;
|
||||
bool intoTerrain;
|
||||
|
||||
Hidden(OSGGeoTransformManipulator *self) : QObject(self), self(self), clampToTerrain(false), intoTerrain(false)
|
||||
{
|
||||
manipulator = new MyManipulator();
|
||||
self->setManipulator(manipulator);
|
||||
}
|
||||
|
||||
~Hidden()
|
||||
{}
|
||||
|
||||
void updateManipulator()
|
||||
{
|
||||
// qDebug() << "OSGGeoTransformManipulator::updateManipulator";
|
||||
|
||||
osg::Matrix cameraMatrix = cameraRotation * cameraPosition;
|
||||
|
||||
manipulator->setByMatrix(cameraMatrix);
|
||||
|
||||
// Inverse the camera's position and orientation matrix to obtain the view matrix
|
||||
cameraMatrix = osg::Matrix::inverse(cameraMatrix);
|
||||
manipulator->setByInverseMatrix(cameraMatrix);
|
||||
}
|
||||
|
||||
void updatePosition()
|
||||
{
|
||||
// qDebug() << "OSGGeoTransformManipulator::updatePosition" << position;
|
||||
|
||||
// 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.
|
||||
// TODO handle the case where the terrain SRS is not "wgs84"
|
||||
// TODO check if position is not below terrain?
|
||||
// TODO compensate antenna height when source of position is GPS (i.e. subtract antenna height from altitude) ;)
|
||||
|
||||
osgEarth::MapNode *mapNode = NULL;
|
||||
|
||||
OSGNode *sceneNode = self->sceneNode();
|
||||
|
||||
if (sceneNode && sceneNode->node()) {
|
||||
mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
|
||||
if (!mapNode) {
|
||||
qWarning() << "OSGGeoTransformManipulator::updatePosition - manipulator node does not contain a map node";
|
||||
}
|
||||
} else {
|
||||
qWarning() << "OSGGeoTransformManipulator::updatePosition - scene node is null";
|
||||
}
|
||||
|
||||
osgEarth::GeoPoint geoPoint;
|
||||
if (mapNode) {
|
||||
geoPoint = osgQtQuick::toGeoPoint(mapNode->getTerrain()->getSRS(), position);
|
||||
} else {
|
||||
geoPoint = osgQtQuick::toGeoPoint(position);
|
||||
}
|
||||
if (clampToTerrain && mapNode) {
|
||||
// clamp model to terrain if needed
|
||||
intoTerrain = osgQtQuick::clampGeoPoint(geoPoint, 0, mapNode);
|
||||
} else if (clampToTerrain) {
|
||||
qWarning() << "OSGGeoTransformManipulator::updatePosition - cannot clamp without map node";
|
||||
}
|
||||
|
||||
geoPoint.createLocalToWorld(cameraPosition);
|
||||
}
|
||||
|
||||
void updateAttitude()
|
||||
{
|
||||
// qDebug() << "OSGGeoTransformManipulator::updateAttitude" << attitude;
|
||||
|
||||
// By default the camera looks toward -Z, we must rotate it so it looks toward Y
|
||||
cameraRotation.makeRotate(osg::DegreesToRadians(90.0), osg::Vec3(1.0, 0.0, 0.0),
|
||||
osg::DegreesToRadians(0.0), osg::Vec3(0.0, 1.0, 0.0),
|
||||
osg::DegreesToRadians(0.0), osg::Vec3(0.0, 0.0, 1.0));
|
||||
|
||||
// Final camera matrix
|
||||
double roll = osg::DegreesToRadians(attitude.x());
|
||||
double pitch = osg::DegreesToRadians(attitude.y());
|
||||
double yaw = osg::DegreesToRadians(attitude.z());
|
||||
cameraRotation = 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));
|
||||
}
|
||||
};
|
||||
|
||||
/* class OSGGeoTransformManipulator::MyManipulator */
|
||||
|
||||
void MyManipulator::updateCamera(osg::Camera & camera)
|
||||
{
|
||||
// qDebug() << "MyManipulator::updateCamera";
|
||||
CameraManipulator::updateCamera(camera);
|
||||
}
|
||||
|
||||
/* class OSGGeoTransformManipulator */
|
||||
|
||||
OSGGeoTransformManipulator::OSGGeoTransformManipulator(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
OSGGeoTransformManipulator::~OSGGeoTransformManipulator()
|
||||
{
|
||||
delete h;
|
||||
}
|
||||
|
||||
bool OSGGeoTransformManipulator::clampToTerrain() const
|
||||
{
|
||||
return h->clampToTerrain;
|
||||
}
|
||||
|
||||
void OSGGeoTransformManipulator::setClampToTerrain(bool arg)
|
||||
{
|
||||
if (h->clampToTerrain != arg) {
|
||||
h->clampToTerrain = arg;
|
||||
setDirty(Clamp);
|
||||
emit clampToTerrainChanged(clampToTerrain());
|
||||
}
|
||||
}
|
||||
|
||||
bool OSGGeoTransformManipulator::intoTerrain() const
|
||||
{
|
||||
return h->intoTerrain;
|
||||
}
|
||||
|
||||
QVector3D OSGGeoTransformManipulator::attitude() const
|
||||
{
|
||||
return h->attitude;
|
||||
}
|
||||
|
||||
void OSGGeoTransformManipulator::setAttitude(QVector3D arg)
|
||||
{
|
||||
if (h->attitude != arg) {
|
||||
h->attitude = arg;
|
||||
setDirty(Attitude);
|
||||
emit attitudeChanged(attitude());
|
||||
}
|
||||
}
|
||||
|
||||
QVector3D OSGGeoTransformManipulator::position() const
|
||||
{
|
||||
return h->position;
|
||||
}
|
||||
|
||||
void OSGGeoTransformManipulator::setPosition(QVector3D arg)
|
||||
{
|
||||
if (h->position != arg) {
|
||||
h->position = arg;
|
||||
setDirty(Position);
|
||||
emit positionChanged(position());
|
||||
}
|
||||
}
|
||||
|
||||
void OSGGeoTransformManipulator::update()
|
||||
{
|
||||
Inherited::update();
|
||||
|
||||
bool b = false;
|
||||
|
||||
if (isDirty(Clamp | Position)) {
|
||||
h->updatePosition();
|
||||
b = true;
|
||||
}
|
||||
if (isDirty(Attitude)) {
|
||||
h->updateAttitude();
|
||||
b = true;
|
||||
}
|
||||
if (b) {
|
||||
h->updateManipulator();
|
||||
}
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGGeoTransformManipulator.moc"
|
@ -0,0 +1,75 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGGeoTransformManipulator.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @brief
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _H_OSGQTQUICK_OSGGEOTRANSFORMMANIPULATOR_H_
|
||||
#define _H_OSGQTQUICK_OSGGEOTRANSFORMMANIPULATOR_H_
|
||||
|
||||
#include "../Export.hpp"
|
||||
#include "OSGCameraManipulator.hpp"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector3D>
|
||||
|
||||
namespace osgQtQuick {
|
||||
class OSGQTQUICK_EXPORT OSGGeoTransformManipulator : public OSGCameraManipulator {
|
||||
Q_OBJECT Q_PROPERTY(QVector3D attitude READ attitude WRITE setAttitude NOTIFY attitudeChanged)
|
||||
Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged)
|
||||
Q_PROPERTY(bool clampToTerrain READ clampToTerrain WRITE setClampToTerrain NOTIFY clampToTerrainChanged)
|
||||
Q_PROPERTY(bool intoTerrain READ intoTerrain NOTIFY intoTerrainChanged)
|
||||
|
||||
typedef OSGCameraManipulator Inherited;
|
||||
|
||||
public:
|
||||
explicit OSGGeoTransformManipulator(QObject *parent = 0);
|
||||
virtual ~OSGGeoTransformManipulator();
|
||||
|
||||
QVector3D attitude() const;
|
||||
void setAttitude(QVector3D arg);
|
||||
|
||||
QVector3D position() const;
|
||||
void setPosition(QVector3D arg);
|
||||
|
||||
bool clampToTerrain() const;
|
||||
void setClampToTerrain(bool arg);
|
||||
|
||||
bool intoTerrain() const;
|
||||
|
||||
signals:
|
||||
void attitudeChanged(QVector3D arg);
|
||||
void positionChanged(QVector3D arg);
|
||||
void clampToTerrainChanged(bool arg);
|
||||
void intoTerrainChanged(bool arg);
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *const h;
|
||||
|
||||
virtual void update();
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#endif // _H_OSGQTQUICK_OSGGEOTRANSFORMMANIPULATOR_H_
|
@ -0,0 +1,175 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGNodeTrackerManipulator.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @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 "OSGNodeTrackerManipulator.hpp"
|
||||
|
||||
#include "../OSGNode.hpp"
|
||||
|
||||
#include <osgGA/NodeTrackerManipulator>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
enum DirtyFlag { TrackNode = 1 << 10, TrackerMode = 1 << 11 };
|
||||
|
||||
struct OSGNodeTrackerManipulator::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OSGNodeTrackerManipulator * const self;
|
||||
|
||||
public:
|
||||
osg::ref_ptr<osgGA::NodeTrackerManipulator> manipulator;
|
||||
|
||||
OSGNode *trackNode;
|
||||
TrackerMode::Enum trackerMode;
|
||||
|
||||
public:
|
||||
Hidden(OSGNodeTrackerManipulator *self) : QObject(self), self(self),
|
||||
trackNode(NULL), trackerMode(TrackerMode::NodeCenterAndAzim)
|
||||
{
|
||||
manipulator = new osgGA::NodeTrackerManipulator(
|
||||
/*osgGA::StandardManipulator::COMPUTE_HOME_USING_BBOX | osgGA::StandardManipulator::DEFAULT_SETTINGS*/);
|
||||
manipulator->setTrackerMode(toOsg(trackerMode));
|
||||
manipulator->setVerticalAxisFixed(false);
|
||||
|
||||
self->setManipulator(manipulator);
|
||||
}
|
||||
|
||||
~Hidden()
|
||||
{}
|
||||
|
||||
bool acceptTrackNode(OSGNode *node)
|
||||
{
|
||||
qDebug() << "OSGNodeTrackerManipulator::acceptTrackNode" << node;
|
||||
if (trackNode == node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (trackNode) {
|
||||
disconnect(trackNode);
|
||||
}
|
||||
|
||||
trackNode = node;
|
||||
|
||||
if (trackNode) {
|
||||
connect(trackNode, &OSGNode::nodeChanged, this, &OSGNodeTrackerManipulator::Hidden::onTrackNodeChanged);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void updateTrackNode()
|
||||
{
|
||||
if (!trackNode) {
|
||||
qWarning() << "OSGNodeTrackerManipulator::updateTrackNode - no track node";
|
||||
return;
|
||||
}
|
||||
qDebug() << "OSGNodeTrackerManipulator::updateTrackNode" << trackNode->node();
|
||||
manipulator->setTrackNode(trackNode->node());
|
||||
}
|
||||
|
||||
void updateTrackerMode()
|
||||
{
|
||||
// qDebug() << "OSGNodeTrackerManipulator::updateTrackerMode" << mode;
|
||||
manipulator->setTrackerMode(toOsg(trackerMode));
|
||||
}
|
||||
|
||||
osgGA::NodeTrackerManipulator::TrackerMode toOsg(TrackerMode::Enum mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case TrackerMode::NodeCenter:
|
||||
return osgGA::NodeTrackerManipulator::NODE_CENTER;
|
||||
|
||||
case TrackerMode::NodeCenterAndAzim:
|
||||
return osgGA::NodeTrackerManipulator::NODE_CENTER_AND_AZIM;
|
||||
|
||||
case TrackerMode::NodeCenterAndRotation:
|
||||
return osgGA::NodeTrackerManipulator::NODE_CENTER_AND_ROTATION;
|
||||
}
|
||||
return osgGA::NodeTrackerManipulator::NODE_CENTER_AND_ROTATION;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void onTrackNodeChanged(osg::Node *node)
|
||||
{
|
||||
qDebug() << "OSGNodeTrackerManipulator::onTrackNodeChanged" << node;
|
||||
qWarning() << "OSGNodeTrackerManipulator::onTrackNodeChanged - needs to be implemented";
|
||||
}
|
||||
};
|
||||
|
||||
/* class OSGNodeTrackerManipulator */
|
||||
|
||||
OSGNodeTrackerManipulator::OSGNodeTrackerManipulator(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
OSGNodeTrackerManipulator::~OSGNodeTrackerManipulator()
|
||||
{
|
||||
delete h;
|
||||
}
|
||||
|
||||
OSGNode *OSGNodeTrackerManipulator::trackNode() const
|
||||
{
|
||||
return h->trackNode;
|
||||
}
|
||||
|
||||
void OSGNodeTrackerManipulator::setTrackNode(OSGNode *node)
|
||||
{
|
||||
if (h->acceptTrackNode(node)) {
|
||||
setDirty(TrackNode);
|
||||
emit trackNodeChanged(node);
|
||||
}
|
||||
}
|
||||
|
||||
TrackerMode::Enum OSGNodeTrackerManipulator::trackerMode() const
|
||||
{
|
||||
return h->trackerMode;
|
||||
}
|
||||
|
||||
void OSGNodeTrackerManipulator::setTrackerMode(TrackerMode::Enum mode)
|
||||
{
|
||||
if (h->trackerMode != mode) {
|
||||
h->trackerMode = mode;
|
||||
setDirty(TrackerMode);
|
||||
emit trackerModeChanged(trackerMode());
|
||||
}
|
||||
}
|
||||
|
||||
void OSGNodeTrackerManipulator::update()
|
||||
{
|
||||
Inherited::update();
|
||||
|
||||
if (isDirty(TrackNode)) {
|
||||
h->updateTrackNode();
|
||||
}
|
||||
if (isDirty(TrackerMode)) {
|
||||
h->updateTrackerMode();
|
||||
}
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGNodeTrackerManipulator.moc"
|
@ -0,0 +1,72 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGNodeTrackerManipulator.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @brief
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _H_OSGQTQUICK_OSGNODETRACKERMANIPULATOR_H_
|
||||
#define _H_OSGQTQUICK_OSGNODETRACKERMANIPULATOR_H_
|
||||
|
||||
#include "../Export.hpp"
|
||||
#include "OSGCameraManipulator.hpp"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace osgQtQuick {
|
||||
class TrackerMode : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Enum { NodeCenter, NodeCenterAndAzim, NodeCenterAndRotation };
|
||||
Q_ENUMS(Enum) // TODO switch to Q_ENUM once on Qt 5.5
|
||||
};
|
||||
|
||||
class OSGQTQUICK_EXPORT OSGNodeTrackerManipulator : public OSGCameraManipulator {
|
||||
Q_OBJECT Q_PROPERTY(osgQtQuick::OSGNode *trackNode READ trackNode WRITE setTrackNode NOTIFY trackNodeChanged)
|
||||
Q_PROPERTY(osgQtQuick::TrackerMode::Enum trackerMode READ trackerMode WRITE setTrackerMode NOTIFY trackerModeChanged)
|
||||
|
||||
typedef OSGCameraManipulator Inherited;
|
||||
|
||||
public:
|
||||
explicit OSGNodeTrackerManipulator(QObject *parent = 0);
|
||||
virtual ~OSGNodeTrackerManipulator();
|
||||
|
||||
OSGNode *trackNode() const;
|
||||
void setTrackNode(OSGNode *node);
|
||||
|
||||
TrackerMode::Enum trackerMode() const;
|
||||
void setTrackerMode(TrackerMode::Enum);
|
||||
|
||||
signals:
|
||||
void trackNodeChanged(OSGNode *node);
|
||||
void trackerModeChanged(TrackerMode::Enum);
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *const h;
|
||||
|
||||
virtual void update();
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#endif // _H_OSGQTQUICK_OSGNODETRACKERMANIPULATOR_H_
|
@ -0,0 +1,69 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGTrackballManipulator.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @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 "OSGTrackballManipulator.hpp"
|
||||
|
||||
#include "../OSGNode.hpp"
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace osgQtQuick {
|
||||
struct OSGTrackballManipulator::Hidden : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OSGTrackballManipulator * const self;
|
||||
|
||||
public:
|
||||
osg::ref_ptr<osgGA::TrackballManipulator> manipulator;
|
||||
|
||||
Hidden(OSGTrackballManipulator *self) : QObject(self), self(self)
|
||||
{
|
||||
manipulator = new osgGA::TrackballManipulator(
|
||||
/*osgGA::StandardManipulator::COMPUTE_HOME_USING_BBOX | osgGA::StandardManipulator::DEFAULT_SETTINGS*/);
|
||||
|
||||
self->setManipulator(manipulator);
|
||||
}
|
||||
|
||||
~Hidden()
|
||||
{}
|
||||
};
|
||||
|
||||
/* class OSGTrackballManipulator */
|
||||
|
||||
OSGTrackballManipulator::OSGTrackballManipulator(QObject *parent) : Inherited(parent), h(new Hidden(this))
|
||||
{}
|
||||
|
||||
OSGTrackballManipulator::~OSGTrackballManipulator()
|
||||
{
|
||||
delete h;
|
||||
}
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#include "OSGTrackballManipulator.moc"
|
@ -0,0 +1,52 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file OSGTrackballManipulator.hpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @brief
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _H_OSGQTQUICK_OSGTRACKBALLMANIPULATOR_H_
|
||||
#define _H_OSGQTQUICK_OSGTRACKBALLMANIPULATOR_H_
|
||||
|
||||
#include "../Export.hpp"
|
||||
#include "OSGCameraManipulator.hpp"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace osgQtQuick {
|
||||
class OSGQTQUICK_EXPORT OSGTrackballManipulator : public OSGCameraManipulator {
|
||||
Q_OBJECT
|
||||
|
||||
typedef OSGCameraManipulator Inherited;
|
||||
|
||||
public:
|
||||
explicit OSGTrackballManipulator(QObject *parent = 0);
|
||||
virtual ~OSGTrackballManipulator();
|
||||
|
||||
private:
|
||||
struct Hidden;
|
||||
Hidden *const h;
|
||||
};
|
||||
} // namespace osgQtQuick
|
||||
|
||||
#endif // _H_OSGQTQUICK_OSGTRACKBALLMANIPULATOR_H_
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file osgearth.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -27,8 +27,8 @@
|
||||
|
||||
#include "osgearth.h"
|
||||
|
||||
#include "utility.h"
|
||||
#include "qtwindowingsystem.h"
|
||||
#include "utils/utility.h"
|
||||
#include "utils/qtwindowingsystem.h"
|
||||
|
||||
#include "utils/pathutils.h"
|
||||
|
||||
@ -107,7 +107,9 @@ void OsgEarth::initialize()
|
||||
|
||||
initializeCache();
|
||||
|
||||
#ifdef OSG_VERBOSE
|
||||
displayInfo();
|
||||
#endif
|
||||
}
|
||||
|
||||
void OsgEarth::initializePathes()
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file osgearth.h
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
|
@ -2,7 +2,7 @@ TEMPLATE = lib
|
||||
TARGET = GCSOsgEarth
|
||||
DEFINES += OSGEARTH_LIBRARY
|
||||
|
||||
#CONFIG += mys2
|
||||
#DEFINES += OSG_VERBOSE
|
||||
|
||||
osg:DEFINES += USE_OSG
|
||||
osgQt:DEFINES += USE_OSG_QT
|
||||
@ -35,40 +35,54 @@ QMAKE_CXXFLAGS += -Wno-unused-parameter
|
||||
|
||||
HEADERS += \
|
||||
osgearth_global.h \
|
||||
utility.h \
|
||||
shapeutils.h \
|
||||
qtwindowingsystem.h \
|
||||
osgearth.h
|
||||
osgearth.h \
|
||||
utils/qtwindowingsystem.h \
|
||||
utils/utility.h \
|
||||
utils/shapeutils.h
|
||||
|
||||
SOURCES += \
|
||||
utility.cpp \
|
||||
shapeutils.cpp \
|
||||
qtwindowingsystem.cpp \
|
||||
osgearth.cpp
|
||||
osgearth.cpp \
|
||||
utils/qtwindowingsystem.cpp \
|
||||
utils/utility.cpp \
|
||||
utils/shapeutils.cpp
|
||||
|
||||
HEADERS += \
|
||||
osgQtQuick/Export.hpp \
|
||||
osgQtQuick/DirtySupport.hpp \
|
||||
osgQtQuick/OSGNode.hpp \
|
||||
osgQtQuick/OSGGroup.hpp \
|
||||
osgQtQuick/OSGTransformNode.hpp \
|
||||
osgQtQuick/OSGShapeNode.hpp \
|
||||
osgQtQuick/OSGImageNode.hpp \
|
||||
osgQtQuick/OSGTextNode.hpp \
|
||||
osgQtQuick/OSGFileNode.hpp \
|
||||
osgQtQuick/OSGBackgroundNode.hpp \
|
||||
osgQtQuick/OSGBillboardNode.hpp \
|
||||
osgQtQuick/OSGCamera.hpp \
|
||||
osgQtQuick/OSGViewport.hpp
|
||||
|
||||
SOURCES += \
|
||||
osgQtQuick/DirtySupport.cpp \
|
||||
osgQtQuick/OSGNode.cpp \
|
||||
osgQtQuick/OSGGroup.cpp \
|
||||
osgQtQuick/OSGTransformNode.cpp \
|
||||
osgQtQuick/OSGShapeNode.cpp \
|
||||
osgQtQuick/OSGImageNode.cpp \
|
||||
osgQtQuick/OSGTextNode.cpp \
|
||||
osgQtQuick/OSGFileNode.cpp \
|
||||
osgQtQuick/OSGBackgroundNode.cpp \
|
||||
osgQtQuick/OSGBillboardNode.cpp \
|
||||
osgQtQuick/OSGCamera.cpp \
|
||||
osgQtQuick/OSGViewport.cpp
|
||||
|
||||
HEADERS += \
|
||||
osgQtQuick/ga/OSGCameraManipulator.hpp \
|
||||
osgQtQuick/ga/OSGNodeTrackerManipulator.hpp \
|
||||
osgQtQuick/ga/OSGTrackballManipulator.hpp
|
||||
|
||||
SOURCES += \
|
||||
osgQtQuick/ga/OSGCameraManipulator.cpp \
|
||||
osgQtQuick/ga/OSGNodeTrackerManipulator.cpp \
|
||||
osgQtQuick/ga/OSGTrackballManipulator.cpp
|
||||
|
||||
osgearth:HEADERS += \
|
||||
osgQtQuick/OSGSkyNode.hpp \
|
||||
osgQtQuick/OSGGeoTransformNode.hpp
|
||||
@ -77,4 +91,12 @@ osgearth:SOURCES += \
|
||||
osgQtQuick/OSGSkyNode.cpp \
|
||||
osgQtQuick/OSGGeoTransformNode.cpp
|
||||
|
||||
osgearth:HEADERS += \
|
||||
osgQtQuick/ga/OSGEarthManipulator.hpp \
|
||||
osgQtQuick/ga/OSGGeoTransformManipulator.hpp
|
||||
|
||||
osgearth:SOURCES += \
|
||||
osgQtQuick/ga/OSGEarthManipulator.cpp \
|
||||
osgQtQuick/ga/OSGGeoTransformManipulator.cpp
|
||||
|
||||
copy_osg:include(copydata.pro)
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file osgearth_global.h
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
|
@ -4,3 +4,6 @@ References :
|
||||
- https://wiki.qt.io/OsgQtQuick-Demo
|
||||
- https://github.com/podsvirov
|
||||
- https://github.com/podsvirov/osgqtquick
|
||||
|
||||
known issues:
|
||||
- http://forum.osgearth.org/VERTEX-glCompileShader-quot-oe-mp-vertModel-quot-FAILED-tt7588106.html#none
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file qtwindowingsystem.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -103,20 +103,20 @@ GraphicsWindowQt::GraphicsWindowQt(osg::GraphicsContext::Traits *traits) :
|
||||
_glContext(NULL),
|
||||
_surface(NULL)
|
||||
{
|
||||
qDebug() << "GraphicsWindowQt::GraphicsWindowQt";
|
||||
// qDebug() << "GraphicsWindowQt::GraphicsWindowQt";
|
||||
_traits = traits;
|
||||
init();
|
||||
}
|
||||
|
||||
GraphicsWindowQt::~GraphicsWindowQt()
|
||||
{
|
||||
qDebug() << "GraphicsWindowQt::~GraphicsWindowQt";
|
||||
// qDebug() << "GraphicsWindowQt::~GraphicsWindowQt";
|
||||
close();
|
||||
}
|
||||
|
||||
void GraphicsWindowQt::init()
|
||||
{
|
||||
qDebug() << "GraphicsWindowQt::init";
|
||||
// qDebug() << "GraphicsWindowQt::init";
|
||||
if (_closing || _initialized) {
|
||||
return;
|
||||
}
|
||||
@ -199,7 +199,7 @@ bool GraphicsWindowQt::valid() const
|
||||
|
||||
bool GraphicsWindowQt::realizeImplementation()
|
||||
{
|
||||
qDebug() << "GraphicsWindowQt::realizeImplementation";
|
||||
// qDebug() << "GraphicsWindowQt::realizeImplementation";
|
||||
// save the current context
|
||||
// note: this will save only Qt-based contexts
|
||||
|
||||
@ -217,16 +217,18 @@ bool GraphicsWindowQt::realizeImplementation()
|
||||
QOpenGLContext *currentContext = QOpenGLContext::currentContext();
|
||||
|
||||
if (!currentContext) {
|
||||
qDebug() << "GraphicsWindowQt::realizeImplementation - creating owned context";
|
||||
// qDebug() << "GraphicsWindowQt::realizeImplementation - creating owned context";
|
||||
_owned = true;
|
||||
_glContext = new QOpenGLContext();
|
||||
_glContext->create();
|
||||
_surface = new QOffscreenSurface();
|
||||
_surface->setFormat(_glContext->format());
|
||||
_surface->create();
|
||||
#ifdef OSG_VERBOSE
|
||||
osgQtQuick::formatInfo(_surface->format());
|
||||
#endif
|
||||
} else {
|
||||
qDebug() << "GraphicsWindowQt::realizeImplementation - using current context";
|
||||
// qDebug() << "GraphicsWindowQt::realizeImplementation - using current context";
|
||||
_glContext = currentContext;
|
||||
}
|
||||
|
||||
@ -316,7 +318,7 @@ bool GraphicsWindowQt::releaseContextImplementation()
|
||||
return false;
|
||||
}
|
||||
if (_owned && _glContext) {
|
||||
qDebug() << "GraphicsWindowQt::releaseContextImplementation";
|
||||
// qDebug() << "GraphicsWindowQt::releaseContextImplementation";
|
||||
_glContext->doneCurrent();
|
||||
}
|
||||
return true;
|
||||
@ -324,14 +326,14 @@ bool GraphicsWindowQt::releaseContextImplementation()
|
||||
|
||||
void GraphicsWindowQt::closeImplementation()
|
||||
{
|
||||
qDebug() << "GraphicsWindowQt::closeImplementation";
|
||||
// qDebug() << "GraphicsWindowQt::closeImplementation";
|
||||
_closing = true;
|
||||
_initialized = false;
|
||||
_valid = false;
|
||||
_realized = false;
|
||||
if (_owned) {
|
||||
if (_glContext) {
|
||||
qDebug() << "GraphicsWindowQt::closeImplementation - deleting owned context";
|
||||
// qDebug() << "GraphicsWindowQt::closeImplementation - deleting owned context";
|
||||
delete _glContext;
|
||||
}
|
||||
if (_surface) {
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file qtwindowingsystem.h
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
@ -1,4 +1,4 @@
|
||||
#include "shapeutils.h"
|
||||
#include "utils/shapeutils.h"
|
||||
|
||||
#include <math.h>
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file utility.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
||||
@ -25,7 +25,7 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "utility.h"
|
||||
#include "utils/utility.h"
|
||||
|
||||
// osgQtQuick qml types
|
||||
#include "osgQtQuick/OSGNode.hpp"
|
||||
@ -33,11 +33,16 @@
|
||||
#include "osgQtQuick/OSGFileNode.hpp"
|
||||
#include "osgQtQuick/OSGTransformNode.hpp"
|
||||
#include "osgQtQuick/OSGShapeNode.hpp"
|
||||
#include "osgQtQuick/OSGImageNode.hpp"
|
||||
#include "osgQtQuick/OSGTextNode.hpp"
|
||||
#include "osgQtQuick/OSGBackgroundNode.hpp"
|
||||
#include "osgQtQuick/OSGBillboardNode.hpp"
|
||||
#include "osgQtQuick/OSGCamera.hpp"
|
||||
#include "osgQtQuick/OSGViewport.hpp"
|
||||
|
||||
#include "osgQtQuick/ga/OSGCameraManipulator.hpp"
|
||||
#include "osgQtQuick/ga/OSGNodeTrackerManipulator.hpp"
|
||||
#include "osgQtQuick/ga/OSGTrackballManipulator.hpp"
|
||||
|
||||
#include <osg/NodeCallback>
|
||||
#include <osg/Camera>
|
||||
#include <osg/MatrixTransform>
|
||||
@ -61,6 +66,9 @@
|
||||
#include "osgQtQuick/OSGSkyNode.hpp"
|
||||
#include "osgQtQuick/OSGGeoTransformNode.hpp"
|
||||
|
||||
#include "osgQtQuick/ga/OSGEarthManipulator.hpp"
|
||||
#include "osgQtQuick/ga/OSGGeoTransformManipulator.hpp"
|
||||
|
||||
#include <osgEarth/Capabilities>
|
||||
#include <osgEarth/MapNode>
|
||||
#include <osgEarth/SpatialReference>
|
||||
@ -75,9 +83,11 @@
|
||||
namespace osgQtQuick {
|
||||
class CullCallback : public osg::NodeCallback {
|
||||
public:
|
||||
CullCallback() {}
|
||||
CullCallback()
|
||||
{}
|
||||
|
||||
virtual ~CullCallback() {}
|
||||
virtual ~CullCallback()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void operator()(osg::Node *node, osg::NodeVisitor *nv)
|
||||
@ -101,12 +111,14 @@ class InsertCallbacksVisitor : public osg::NodeVisitor {
|
||||
public:
|
||||
InsertCallbacksVisitor() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{}
|
||||
|
||||
virtual void apply(osg::Node & node)
|
||||
{
|
||||
// node.setUpdateCallback(new UpdateCallback());
|
||||
node.setCullCallback(new CullCallback());
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
virtual void apply(osg::Geode & geode)
|
||||
{
|
||||
// geode.setUpdateCallback(new UpdateCallback());
|
||||
@ -122,6 +134,7 @@ public:
|
||||
// geode.getDrawable(i)->setDrawCallback(new DrawableDrawCallback());
|
||||
// }
|
||||
}
|
||||
|
||||
virtual void apply(osg::Transform & node)
|
||||
{
|
||||
apply((osg::Node &)node);
|
||||
@ -469,7 +482,7 @@ bool clampGeoPoint(osgEarth::GeoPoint &geoPoint, float offset, osgEarth::MapNode
|
||||
if (eq.getElevation(geoPoint, elevation, 0.0)) {
|
||||
clamped = ((geoPoint.z() - offset) < elevation);
|
||||
if (clamped) {
|
||||
qDebug() << "Utility::clampGeoPoint - clamping" << geoPoint.z() - offset << "/" << elevation;
|
||||
// qDebug() << "Utility::clampGeoPoint - clamping" << geoPoint.z() - offset << "/" << elevation;
|
||||
geoPoint.z() = elevation + offset;
|
||||
}
|
||||
} else {
|
||||
@ -522,33 +535,45 @@ void registerTypes()
|
||||
{
|
||||
int maj = 1, min = 0;
|
||||
|
||||
// @uri osgQtQuick
|
||||
// viewport
|
||||
qmlRegisterType<osgQtQuick::OSGViewport>("OsgQtQuick", maj, min, "OSGViewport");
|
||||
qmlRegisterType<osgQtQuick::UpdateMode>("OsgQtQuick", maj, min, "UpdateMode");
|
||||
|
||||
// basic nodes
|
||||
qmlRegisterType<osgQtQuick::OSGNode>("OsgQtQuick", maj, min, "OSGNode");
|
||||
|
||||
qmlRegisterType<osgQtQuick::OSGGroup>("OsgQtQuick", maj, min, "OSGGroup");
|
||||
|
||||
qmlRegisterType<osgQtQuick::OSGFileNode>("OsgQtQuick", maj, min, "OSGFileNode");
|
||||
qmlRegisterType<osgQtQuick::OptimizeMode>("OsgQtQuick", maj, min, "OptimizeMode");
|
||||
|
||||
qmlRegisterType<osgQtQuick::OSGTransformNode>("OsgQtQuick", maj, min, "OSGTransformNode");
|
||||
|
||||
qmlRegisterType<osgQtQuick::OSGTextNode>("OsgQtQuick", maj, min, "OSGTextNode");
|
||||
|
||||
// primitive nodes
|
||||
qmlRegisterType<osgQtQuick::OSGShapeNode>("OsgQtQuick", maj, min, "OSGShapeNode");
|
||||
qmlRegisterType<osgQtQuick::ShapeType>("OsgQtQuick", maj, min, "ShapeType");
|
||||
|
||||
qmlRegisterType<osgQtQuick::OSGBackgroundNode>("OsgQtQuick", maj, min, "OSGBackgroundNode");
|
||||
qmlRegisterType<osgQtQuick::OSGImageNode>("OsgQtQuick", maj, min, "OSGImageNode");
|
||||
|
||||
qmlRegisterType<osgQtQuick::OSGViewport>("OsgQtQuick", maj, min, "OSGViewport");
|
||||
qmlRegisterType<osgQtQuick::UpdateMode>("OsgQtQuick", maj, min, "UpdateMode");
|
||||
qmlRegisterType<osgQtQuick::OSGTextNode>("OsgQtQuick", maj, min, "OSGTextNode");
|
||||
|
||||
qmlRegisterType<osgQtQuick::OSGBillboardNode>("OsgQtQuick", maj, min, "OSGBillboardNode");
|
||||
|
||||
qmlRegisterType<osgQtQuick::OSGFileNode>("OsgQtQuick", maj, min, "OSGFileNode");
|
||||
qmlRegisterType<osgQtQuick::OptimizeMode>("OsgQtQuick", maj, min, "OptimizeMode");
|
||||
|
||||
// camera nodes
|
||||
qmlRegisterType<osgQtQuick::OSGCamera>("OsgQtQuick", maj, min, "OSGCamera");
|
||||
qmlRegisterType<osgQtQuick::ManipulatorMode>("OsgQtQuick", maj, min, "ManipulatorMode");
|
||||
|
||||
// camera manipulators
|
||||
qmlRegisterType<osgQtQuick::OSGCameraManipulator>("OsgQtQuick", maj, min, "OSGCameraManipulator");
|
||||
qmlRegisterType<osgQtQuick::OSGNodeTrackerManipulator>("OsgQtQuick", maj, min, "OSGNodeTrackerManipulator");
|
||||
qmlRegisterType<osgQtQuick::TrackerMode>("OsgQtQuick", maj, min, "TrackerMode");
|
||||
qmlRegisterType<osgQtQuick::OSGTrackballManipulator>("OsgQtQuick", maj, min, "OSGTrackballManipulator");
|
||||
|
||||
#ifdef USE_OSGEARTH
|
||||
qmlRegisterType<osgQtQuick::OSGSkyNode>("OsgQtQuick", maj, min, "OSGSkyNode");
|
||||
qmlRegisterType<osgQtQuick::OSGGeoTransformNode>("OsgQtQuick", maj, min, "OSGGeoTransformNode");
|
||||
|
||||
qmlRegisterType<osgQtQuick::OSGEarthManipulator>("OsgQtQuick", maj, min, "OSGEarthManipulator");
|
||||
qmlRegisterType<osgQtQuick::OSGGeoTransformManipulator>("OsgQtQuick", maj, min, "OSGGeoTransformManipulator");
|
||||
#endif // USE_OSGEARTH
|
||||
}
|
||||
} // namespace osgQtQuick
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file utility.h
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
|
||||
* @addtogroup
|
||||
* @{
|
||||
* @addtogroup
|
@ -127,16 +127,16 @@ void QuickWidgetProxy::onStatusChanged(QQuickWidget::Status status)
|
||||
{
|
||||
switch (status) {
|
||||
case QQuickWidget::Null:
|
||||
qDebug() << "QuickWidgetProxy - status Null";
|
||||
qWarning() << "QuickWidgetProxy - status Null";
|
||||
break;
|
||||
case QQuickWidget::Ready:
|
||||
qDebug() << "QuickWidgetProxy - status Ready";
|
||||
// qDebug() << "QuickWidgetProxy - status Ready";
|
||||
break;
|
||||
case QQuickWidget::Loading:
|
||||
qDebug() << "QuickWidgetProxy - status Loading";
|
||||
// qDebug() << "QuickWidgetProxy - status Loading";
|
||||
break;
|
||||
case QQuickWidget::Error:
|
||||
qDebug() << "QuickWidgetProxy - status Error";
|
||||
qWarning() << "QuickWidgetProxy - status Error";
|
||||
foreach(const QQmlError &error, errors()) {
|
||||
qWarning() << error.description();
|
||||
}
|
||||
@ -148,16 +148,16 @@ void QuickWidgetProxy::onStatusChanged(QQuickView::Status status)
|
||||
{
|
||||
switch (status) {
|
||||
case QQuickView::Null:
|
||||
qDebug() << "QuickWidgetProxy - status Null";
|
||||
qWarning() << "QuickWidgetProxy - status Null";
|
||||
break;
|
||||
case QQuickView::Ready:
|
||||
qDebug() << "QuickWidgetProxy - status Ready";
|
||||
// qDebug() << "QuickWidgetProxy - status Ready";
|
||||
break;
|
||||
case QQuickView::Loading:
|
||||
qDebug() << "QuickWidgetProxy - status Loading";
|
||||
// qDebug() << "QuickWidgetProxy - status Loading";
|
||||
break;
|
||||
case QQuickView::Error:
|
||||
qDebug() << "QuickWidgetProxy - status Error";
|
||||
qWarning() << "QuickWidgetProxy - status Error";
|
||||
foreach(const QQmlError &error, errors()) {
|
||||
qWarning() << error.description();
|
||||
}
|
||||
|
@ -28,13 +28,18 @@
|
||||
#include "pfdqmlcontext.h"
|
||||
|
||||
#include "extensionsystem/pluginmanager.h"
|
||||
#include "uavobjectmanager.h"
|
||||
#include "uavobject.h"
|
||||
#include "uavobjectmanager.h"
|
||||
#include "utils/stringutils.h"
|
||||
#include "utils/pathutils.h"
|
||||
|
||||
#include "flightbatterysettings.h"
|
||||
|
||||
#include <QQmlContext>
|
||||
#include <QDebug>
|
||||
#include <QDirIterator>
|
||||
|
||||
const QString PfdQmlContext::CONTEXT_PROPERTY_NAME = "pfdContext";
|
||||
|
||||
PfdQmlContext::PfdQmlContext(QObject *parent) : QObject(parent),
|
||||
m_speedUnit("m/s"),
|
||||
@ -50,8 +55,13 @@ PfdQmlContext::PfdQmlContext(QObject *parent) : QObject(parent),
|
||||
m_dateTime(QDateTime()),
|
||||
m_minAmbientLight(0.03),
|
||||
m_modelFile(""),
|
||||
m_modelIndex(0),
|
||||
m_backgroundImageFile("")
|
||||
{}
|
||||
{
|
||||
addModelDir("helis");
|
||||
addModelDir("multi");
|
||||
addModelDir("planes");
|
||||
}
|
||||
|
||||
PfdQmlContext::~PfdQmlContext()
|
||||
{}
|
||||
@ -220,11 +230,32 @@ QString PfdQmlContext::modelFile() const
|
||||
void PfdQmlContext::setModelFile(const QString &arg)
|
||||
{
|
||||
if (m_modelFile != arg) {
|
||||
m_modelFile = arg;
|
||||
m_modelFile = arg;
|
||||
m_modelIndex = m_modelFileList.indexOf(m_modelFile);
|
||||
if (m_modelIndex == -1) {
|
||||
m_modelIndex = 0;
|
||||
}
|
||||
emit modelFileChanged(modelFile());
|
||||
}
|
||||
}
|
||||
|
||||
void PfdQmlContext::nextModel()
|
||||
{
|
||||
m_modelIndex = (m_modelIndex + 1) % m_modelFileList.length();
|
||||
setModelFile(m_modelFileList[m_modelIndex]);
|
||||
}
|
||||
|
||||
void PfdQmlContext::previousModel()
|
||||
{
|
||||
m_modelIndex = (m_modelFileList.length() + m_modelIndex - 1) % m_modelFileList.length();
|
||||
setModelFile(m_modelFileList[m_modelIndex]);
|
||||
}
|
||||
|
||||
QStringList PfdQmlContext::modelFileList() const
|
||||
{
|
||||
return m_modelFileList;
|
||||
}
|
||||
|
||||
QString PfdQmlContext::backgroundImageFile() const
|
||||
{
|
||||
return m_backgroundImageFile;
|
||||
@ -281,12 +312,16 @@ void PfdQmlContext::loadConfiguration(PfdQmlGadgetConfiguration *config)
|
||||
|
||||
void PfdQmlContext::saveState(QSettings *settings)
|
||||
{
|
||||
Q_UNUSED(settings);
|
||||
settings->setValue("modelFile", modelFile());
|
||||
}
|
||||
|
||||
void PfdQmlContext::restoreState(QSettings *settings)
|
||||
{
|
||||
Q_UNUSED(settings);
|
||||
QString file = settings->value("modelFile").toString();
|
||||
|
||||
if (!file.isEmpty()) {
|
||||
setModelFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
void PfdQmlContext::apply(QQmlContext *context)
|
||||
@ -339,6 +374,17 @@ void PfdQmlContext::apply(QQmlContext *context)
|
||||
}
|
||||
}
|
||||
|
||||
// to expose settings values
|
||||
context->setContextProperty("pfdContext", this);
|
||||
// expose this context to Qml
|
||||
context->setContextProperty(CONTEXT_PROPERTY_NAME, this);
|
||||
}
|
||||
|
||||
void PfdQmlContext::addModelDir(QString dir)
|
||||
{
|
||||
QDirIterator it(Utils::GetDataPath() + "models/" + dir, QStringList("*.3ds"), QDir::NoFilter, QDirIterator::Subdirectories);
|
||||
|
||||
while (it.hasNext()) {
|
||||
QString file = QDir::toNativeSeparators(it.next());
|
||||
// qDebug() << file;
|
||||
m_modelFileList.append(file);
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,11 @@ class PfdQmlContext : public QObject {
|
||||
Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY dateTimeChanged)
|
||||
Q_PROPERTY(double minimumAmbientLight READ minimumAmbientLight WRITE setMinimumAmbientLight NOTIFY minimumAmbientLightChanged)
|
||||
|
||||
Q_PROPERTY(QString modelFile READ modelFile WRITE setModelFile NOTIFY modelFileChanged)
|
||||
// model
|
||||
Q_PROPERTY(QString modelFile READ modelFile NOTIFY modelFileChanged)
|
||||
Q_PROPERTY(QStringList modelFileList READ modelFileList CONSTANT FINAL)
|
||||
|
||||
// background
|
||||
Q_PROPERTY(QString backgroundImageFile READ backgroundImageFile WRITE setBackgroundImageFile NOTIFY backgroundImageFileChanged)
|
||||
|
||||
public:
|
||||
@ -87,8 +91,14 @@ public:
|
||||
double minimumAmbientLight() const;
|
||||
void setMinimumAmbientLight(double arg);
|
||||
|
||||
// model
|
||||
QString modelFile() const;
|
||||
void setModelFile(const QString &arg);
|
||||
QStringList modelFileList() const;
|
||||
Q_INVOKABLE void nextModel();
|
||||
Q_INVOKABLE void previousModel();
|
||||
|
||||
// background
|
||||
QString backgroundImageFile() const;
|
||||
void setBackgroundImageFile(const QString &arg);
|
||||
|
||||
@ -121,6 +131,9 @@ signals:
|
||||
void backgroundImageFileChanged(QString arg);
|
||||
|
||||
private:
|
||||
// constants
|
||||
static const QString CONTEXT_PROPERTY_NAME;
|
||||
|
||||
QString m_speedUnit;
|
||||
double m_speedFactor;
|
||||
QString m_altitudeUnit;
|
||||
@ -138,7 +151,11 @@ private:
|
||||
double m_minAmbientLight;
|
||||
|
||||
QString m_modelFile;
|
||||
int m_modelIndex;
|
||||
QStringList m_modelFileList;
|
||||
|
||||
QString m_backgroundImageFile;
|
||||
|
||||
void addModelDir(QString dir);
|
||||
};
|
||||
#endif /* PFDQMLCONTEXT_H_ */
|
||||
|
@ -52,14 +52,10 @@ WelcomePlugin::WelcomePlugin()
|
||||
|
||||
WelcomePlugin::~WelcomePlugin()
|
||||
{
|
||||
// The below code is commented out to avoid having the application
|
||||
// crash when it is terminated. TODO: Fix a real solution.
|
||||
/*
|
||||
if (m_welcomeMode) {
|
||||
if (m_welcomeMode) {
|
||||
removeObject(m_welcomeMode);
|
||||
delete m_welcomeMode;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/*! Initializes the plugin. Returns true on success.
|
||||
|
@ -1635,7 +1635,7 @@
|
||||
<version>0.0.0</version>
|
||||
</configInfo>
|
||||
<data>
|
||||
<qmlFile>%%DATAPATH%%qml/Pfd.qml</qmlFile>
|
||||
<qmlFile>%%DATAPATH%%qml/PfdTerrain.qml</qmlFile>
|
||||
<altitudeFactor>1</altitudeFactor>
|
||||
<speedFactor>1</speedFactor>
|
||||
<terrainEnabled>true</terrainEnabled>
|
||||
@ -1659,7 +1659,7 @@
|
||||
<version>0.0.0</version>
|
||||
</configInfo>
|
||||
<data>
|
||||
<qmlFile>%%DATAPATH%%qml/Pfd.qml</qmlFile>
|
||||
<qmlFile>%%DATAPATH%%qml/PfdTerrain.qml</qmlFile>
|
||||
<altitudeFactor>1</altitudeFactor>
|
||||
<speedFactor>1</speedFactor>
|
||||
<terrainEnabled>true</terrainEnabled>
|
||||
@ -1683,7 +1683,7 @@
|
||||
<version>0.0.0</version>
|
||||
</configInfo>
|
||||
<data>
|
||||
<qmlFile>%%DATAPATH%%qml/ModelView.qml</qmlFile>
|
||||
<qmlFile>%%DATAPATH%%qml/Model.qml</qmlFile>
|
||||
<altitudeFactor>1</altitudeFactor>
|
||||
<speedFactor>1</speedFactor>
|
||||
<terrainEnabled>false</terrainEnabled>
|
||||
@ -1707,7 +1707,7 @@
|
||||
<version>0.0.0</version>
|
||||
</configInfo>
|
||||
<data>
|
||||
<qmlFile>%%DATAPATH%%qml/ModelView.qml</qmlFile>
|
||||
<qmlFile>%%DATAPATH%%qml/ModelTerrain.qml</qmlFile>
|
||||
<altitudeFactor>1</altitudeFactor>
|
||||
<speedFactor>1</speedFactor>
|
||||
<terrainEnabled>true</terrainEnabled>
|
||||
@ -1731,7 +1731,7 @@
|
||||
<version>0.0.0</version>
|
||||
</configInfo>
|
||||
<data>
|
||||
<qmlFile>%%DATAPATH%%qml/ModelView.qml</qmlFile>
|
||||
<qmlFile>%%DATAPATH%%qml/ModelTerrain.qml</qmlFile>
|
||||
<altitudeFactor>1</altitudeFactor>
|
||||
<speedFactor>1</speedFactor>
|
||||
<terrainEnabled>true</terrainEnabled>
|
||||
@ -1755,7 +1755,7 @@
|
||||
<version>0.0.0</version>
|
||||
</configInfo>
|
||||
<data>
|
||||
<qmlFile>%%DATAPATH%%qml/EarthView.qml</qmlFile>
|
||||
<qmlFile>%%DATAPATH%%qml/Earth.qml</qmlFile>
|
||||
<altitudeFactor>1</altitudeFactor>
|
||||
<speedFactor>1</speedFactor>
|
||||
<terrainEnabled>true</terrainEnabled>
|
||||
|
@ -18,22 +18,37 @@
|
||||
* along with LibrePilot GCS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import Pfd 1.0
|
||||
import OsgQtQuick 1.0
|
||||
|
||||
import "common.js" as Utils
|
||||
import "js/common.js" as Utils
|
||||
|
||||
Item {
|
||||
OSGViewport {
|
||||
id: osgViewport
|
||||
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
sceneData: skyNode
|
||||
|
||||
sceneNode: skyNode
|
||||
camera: camera
|
||||
manipulator: earthManipulator
|
||||
|
||||
OSGCamera {
|
||||
id: camera
|
||||
fieldOfView: 90
|
||||
}
|
||||
|
||||
OSGEarthManipulator {
|
||||
id: earthManipulator
|
||||
}
|
||||
|
||||
OSGSkyNode {
|
||||
id: skyNode
|
||||
sceneData: terrainNode
|
||||
sceneNode: terrainNode
|
||||
viewport: osgViewport
|
||||
dateTime: Utils.getDateTime()
|
||||
minimumAmbientLight: pfdContext.minimumAmbientLight
|
||||
}
|
||||
@ -44,11 +59,25 @@ Item {
|
||||
async: false
|
||||
}
|
||||
|
||||
OSGCamera {
|
||||
id: camera
|
||||
fieldOfView: 90
|
||||
manipulatorMode: ManipulatorMode.Earth
|
||||
}
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
width: 24
|
||||
height: 24
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 4
|
||||
|
||||
running: osgViewport.busy
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
width: 24
|
||||
height: 24
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 4
|
||||
|
||||
running: osgViewport.busy
|
||||
}
|
||||
}
|
@ -19,10 +19,7 @@
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
Item {
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
source: pfdContext.terrainEnabled ? "model/ModelTerrainView.qml" : "model/ModelView.qml"
|
||||
}
|
||||
}
|
||||
import "model"
|
||||
|
||||
ModelView {
|
||||
}
|
25
ground/gcs/src/share/qml/ModelTerrain.qml
Normal file
25
ground/gcs/src/share/qml/ModelTerrain.qml
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The LibrePilot Project
|
||||
* Contact: http://www.librepilot.org
|
||||
*
|
||||
* This file is part of LibrePilot GCS.
|
||||
*
|
||||
* LibrePilot GCS 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.
|
||||
*
|
||||
* LibrePilot GCS 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 LibrePilot GCS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
import "model"
|
||||
|
||||
ModelTerrainView {
|
||||
}
|
@ -19,107 +19,8 @@
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
import "pfd" as Pfd
|
||||
import "pfd"
|
||||
|
||||
Rectangle {
|
||||
color: "#515151"
|
||||
|
||||
Pfd.SvgElementImage {
|
||||
id: background
|
||||
elementName: "pfd-window"
|
||||
fillMode: Image.PreserveAspectFit
|
||||
anchors.fill: parent
|
||||
sceneSize: Qt.size(width, height)
|
||||
|
||||
Rectangle {
|
||||
width: Math.floor(parent.paintedHeight * 1.319)
|
||||
height: Math.floor(parent.paintedHeight - parent.paintedHeight * 0.008)
|
||||
|
||||
color: "transparent"
|
||||
border.color: "white"
|
||||
border.width: Math.floor(parent.paintedHeight * 0.008)
|
||||
radius: Math.floor(parent.paintedHeight * 0.01)
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
Item {
|
||||
id: sceneItem
|
||||
|
||||
FontLoader {
|
||||
id: pt_bold
|
||||
source: "qrc:/utils/fonts/PTS75F.ttf"
|
||||
}
|
||||
|
||||
width: Math.floor((parent.paintedHeight * 1.32) - (parent.paintedHeight * 0.013))
|
||||
height: Math.floor(parent.paintedHeight - parent.paintedHeight * 0.02)
|
||||
property variant viewportSize : Qt.size(width, height)
|
||||
|
||||
anchors.centerIn: parent
|
||||
clip: true
|
||||
|
||||
Loader {
|
||||
id: worldLoader
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
source: pfdContext.terrainEnabled ? "pfd/PfdTerrainView.qml" : "pfd/PfdWorldView.qml"
|
||||
}
|
||||
|
||||
Pfd.HorizontCenter {
|
||||
id: horizontCenterItem
|
||||
sceneSize: sceneItem.viewportSize
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Pfd.RollScale {
|
||||
id: rollscale
|
||||
sceneSize: sceneItem.viewportSize
|
||||
horizontCenter: horizontCenterItem.horizontCenter
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Pfd.SvgElementImage {
|
||||
id: side_slip_fixed
|
||||
elementName: "sideslip-fixed"
|
||||
sceneSize: sceneItem.viewportSize
|
||||
|
||||
x: scaledBounds.x * sceneItem.width
|
||||
}
|
||||
|
||||
Pfd.Compass {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
}
|
||||
|
||||
Pfd.SpeedScale {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
}
|
||||
|
||||
Pfd.AltitudeScale {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
}
|
||||
|
||||
Pfd.VsiScale {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
visible: pfdContext.altitudeUnit != 0
|
||||
}
|
||||
|
||||
Pfd.Info {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
}
|
||||
|
||||
Pfd.Panels {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
}
|
||||
|
||||
Pfd.Warnings {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
}
|
||||
}
|
||||
}
|
||||
PfdView {
|
||||
worldFile: "PfdSimpleWorld.qml"
|
||||
}
|
||||
|
27
ground/gcs/src/share/qml/PfdTerrain.qml
Normal file
27
ground/gcs/src/share/qml/PfdTerrain.qml
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The LibrePilot Project
|
||||
* Contact: http://www.librepilot.org
|
||||
*
|
||||
* This file is part of LibrePilot GCS.
|
||||
*
|
||||
* LibrePilot GCS 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.
|
||||
*
|
||||
* LibrePilot GCS 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 LibrePilot GCS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
import "pfd"
|
||||
|
||||
PfdView {
|
||||
opaque: false
|
||||
worldFile: "PfdTerrainWorld.qml"
|
||||
}
|
@ -28,7 +28,7 @@
|
||||
.import UAVTalk.VtolPathFollowerSettings 1.0 as VtolPathFollowerSettings
|
||||
|
||||
// Navigation
|
||||
.import UAVTalk.HomeLocation 1.0 as HomeLocation
|
||||
.import UAVTalk.HomeLocation 1.0 as HomeLocation
|
||||
.import UAVTalk.TakeOffLocation 1.0 as TakeOffLocation
|
||||
|
||||
// Sensors
|
||||
@ -147,7 +147,7 @@ function defaultPosition() {
|
||||
*
|
||||
*/
|
||||
function isCC3D() {
|
||||
// Hack: detect Coptercontrol with mem free
|
||||
// Hack: detect Coptercontrol with mem free
|
||||
return (freeMemoryBytes() < 3096);
|
||||
}
|
||||
|
||||
@ -251,7 +251,7 @@ function gpsStatus() {
|
||||
return ["NO GPS", "NO FIX", "2D", "3D"][gpsPositionSensor.status];
|
||||
}
|
||||
|
||||
function fusionAlgorithm() {
|
||||
function fusionAlgorithm() {
|
||||
return ["None", "Basic (No Nav)", "CompMag", "Comp+Mag+GPS", "EKFIndoor", "GPSNav (INS13)"][revoSettings.fusionAlgorithm];
|
||||
}
|
||||
|
||||
@ -271,7 +271,7 @@ function batteryModuleEnabled() {
|
||||
return (hwSettings.optionalModulesBattery == HwSettings.OptionalModules.Enabled);
|
||||
}
|
||||
|
||||
function batteryNbCells() {
|
||||
function batteryNbCells() {
|
||||
return flightBatterySettings.nbCells;
|
||||
}
|
||||
|
||||
@ -287,7 +287,7 @@ function batteryConsumedEnergy() {
|
||||
return flightBatteryState.consumedEnergy.toFixed(0);
|
||||
}
|
||||
|
||||
function estimatedFlightTimeValue() {
|
||||
function estimatedFlightTimeValue() {
|
||||
return Math.round(flightBatteryState.estimatedFlightTime);
|
||||
}
|
||||
|
||||
@ -351,7 +351,7 @@ function waypointHeading() {
|
||||
}
|
||||
|
||||
function homeDistance() {
|
||||
return Math.sqrt(Math.pow((takeOffLocation.east - positionState.east), 2) +
|
||||
return Math.sqrt(Math.pow((takeOffLocation.east - positionState.east), 2) +
|
||||
Math.pow((takeOffLocation.north - positionState.north), 2));
|
||||
}
|
||||
|
||||
@ -377,8 +377,8 @@ function isVtolPathFollowerSettingsThrustAuto() {
|
||||
}
|
||||
|
||||
function flightModeName() {
|
||||
return ["MANUAL", "STAB 1", "STAB 2", "STAB 3", "STAB 4", "STAB 5", "STAB 6",
|
||||
"POS HOLD", "COURSELOCK", "VEL ROAM", "HOME LEASH", "ABS POS", "RTB",
|
||||
return ["MANUAL", "STAB 1", "STAB 2", "STAB 3", "STAB 4", "STAB 5", "STAB 6",
|
||||
"POS HOLD", "COURSELOCK", "VEL ROAM", "HOME LEASH", "ABS POS", "RTB",
|
||||
"LAND", "PATHPLAN", "POI", "AUTOCRUISE", "AUTOTAKEOFF"][flightStatus.flightMode];
|
||||
}
|
||||
|
@ -18,75 +18,105 @@
|
||||
* along with LibrePilot GCS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import Pfd 1.0
|
||||
import OsgQtQuick 1.0
|
||||
|
||||
import "../common.js" as Utils
|
||||
import "../uav.js" as UAV
|
||||
import "../js/common.js" as Utils
|
||||
import "../js/uav.js" as UAV
|
||||
|
||||
OSGViewport {
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
sceneData: skyNode
|
||||
camera: camera
|
||||
Item {
|
||||
OSGViewport {
|
||||
id: osgViewport
|
||||
|
||||
OSGSkyNode {
|
||||
id: skyNode
|
||||
sceneData: sceneGroup
|
||||
dateTime: Utils.getDateTime()
|
||||
minimumAmbientLight: pfdContext.minimumAmbientLight
|
||||
}
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
|
||||
OSGGroup {
|
||||
id: sceneGroup
|
||||
children: [ terrainNode, modelNode ]
|
||||
}
|
||||
sceneNode: skyNode
|
||||
camera: camera
|
||||
manipulator: nodeTrackerManipulator
|
||||
|
||||
OSGFileNode {
|
||||
id: terrainNode
|
||||
source: pfdContext.terrainFile
|
||||
async: false
|
||||
}
|
||||
OSGCamera {
|
||||
id: camera
|
||||
fieldOfView: 90
|
||||
logarithmicDepthBuffer: true
|
||||
}
|
||||
|
||||
OSGGeoTransformNode {
|
||||
id: modelNode
|
||||
OSGNodeTrackerManipulator {
|
||||
id: nodeTrackerManipulator
|
||||
// use model to compute camera home position
|
||||
sceneNode: modelTransformNode
|
||||
// model will be tracked
|
||||
trackNode: modelTransformNode
|
||||
}
|
||||
|
||||
modelData: modelTransformNode
|
||||
sceneData: terrainNode
|
||||
OSGSkyNode {
|
||||
id: skyNode
|
||||
sceneNode: sceneGroup
|
||||
viewport: osgViewport
|
||||
dateTime: Utils.getDateTime()
|
||||
minimumAmbientLight: pfdContext.minimumAmbientLight
|
||||
}
|
||||
|
||||
clampToTerrain: true
|
||||
OSGGroup {
|
||||
id: sceneGroup
|
||||
children: [ terrainFileNode, modelNode ]
|
||||
}
|
||||
|
||||
position: UAV.position()
|
||||
}
|
||||
OSGGeoTransformNode {
|
||||
id: modelNode
|
||||
|
||||
OSGTransformNode {
|
||||
id: modelTransformNode
|
||||
modelData: modelFileNode
|
||||
// model dimensions are in mm, scale to meters
|
||||
scale: Qt.vector3d(0.001, 0.001, 0.001)
|
||||
attitude: UAV.attitude()
|
||||
}
|
||||
sceneNode: terrainFileNode
|
||||
children: [ modelTransformNode ]
|
||||
|
||||
OSGFileNode {
|
||||
id: modelFileNode
|
||||
clampToTerrain: true
|
||||
|
||||
// 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"
|
||||
position: UAV.position()
|
||||
}
|
||||
|
||||
async: false
|
||||
optimizeMode: OptimizeMode.OptimizeAndCheck
|
||||
}
|
||||
OSGTransformNode {
|
||||
id: modelTransformNode
|
||||
|
||||
children: [ modelFileNode ]
|
||||
|
||||
// model dimensions are in mm, scale to meters
|
||||
scale: Qt.vector3d(0.001, 0.001, 0.001)
|
||||
attitude: UAV.attitude()
|
||||
}
|
||||
|
||||
OSGFileNode {
|
||||
id: terrainFileNode
|
||||
source: pfdContext.terrainFile
|
||||
}
|
||||
|
||||
OSGFileNode {
|
||||
id: modelFileNode
|
||||
|
||||
// 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"
|
||||
|
||||
optimizeMode: OptimizeMode.OptimizeAndCheck
|
||||
}
|
||||
|
||||
Keys.onUpPressed: {
|
||||
pfdContext.nextModel();
|
||||
}
|
||||
|
||||
Keys.onDownPressed: {
|
||||
pfdContext.previousModel();
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
width: 24
|
||||
height: 24
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 4
|
||||
|
||||
running: osgViewport.busy
|
||||
}
|
||||
|
||||
OSGCamera {
|
||||
id: camera
|
||||
fieldOfView: 90
|
||||
logarithmicDepthBuffer: true
|
||||
manipulatorMode: ManipulatorMode.Track
|
||||
// use model to compute camera home position
|
||||
sceneNode: modelTransformNode
|
||||
// model will be tracked
|
||||
trackNode: modelTransformNode
|
||||
}
|
||||
}
|
||||
|
@ -21,32 +21,48 @@ import QtQuick 2.4
|
||||
|
||||
import OsgQtQuick 1.0
|
||||
|
||||
import "../uav.js" as UAV
|
||||
import "../js/uav.js" as UAV
|
||||
|
||||
Item {
|
||||
|
||||
OSGViewport {
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
sceneData: sceneNode
|
||||
|
||||
sceneNode: sceneNode
|
||||
camera: camera
|
||||
manipulator: trackballManipulator
|
||||
|
||||
OSGCamera {
|
||||
id: camera
|
||||
fieldOfView: 90
|
||||
}
|
||||
|
||||
OSGTrackballManipulator {
|
||||
id: trackballManipulator
|
||||
sceneNode: transformNode
|
||||
}
|
||||
|
||||
OSGGroup {
|
||||
id: sceneNode
|
||||
children: [
|
||||
transformNode,
|
||||
backgroundNode
|
||||
]
|
||||
children: [ transformNode, backgroundNode ]
|
||||
}
|
||||
|
||||
OSGBackgroundNode {
|
||||
OSGBillboardNode {
|
||||
id: backgroundNode
|
||||
children: [ backgroundImageNode ]
|
||||
}
|
||||
|
||||
OSGImageNode {
|
||||
id: backgroundImageNode
|
||||
imageFile: pfdContext.backgroundImageFile
|
||||
}
|
||||
|
||||
OSGTransformNode {
|
||||
id: transformNode
|
||||
modelData: fileNode
|
||||
|
||||
children: [ fileNode ]
|
||||
|
||||
attitude: UAV.attitude()
|
||||
}
|
||||
|
||||
@ -57,10 +73,12 @@ Item {
|
||||
optimizeMode: OptimizeMode.OptimizeAndCheck
|
||||
}
|
||||
|
||||
OSGCamera {
|
||||
id: camera
|
||||
fieldOfView: 90
|
||||
sceneNode: transformNode
|
||||
Keys.onUpPressed: {
|
||||
pfdContext.nextModel();
|
||||
}
|
||||
|
||||
Keys.onDownPressed: {
|
||||
pfdContext.previousModel();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,8 @@
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
import "../common.js" as Utils
|
||||
import "../uav.js" as UAV
|
||||
import "../js/common.js" as Utils
|
||||
import "../js/uav.js" as UAV
|
||||
|
||||
Item {
|
||||
id: sceneItem
|
||||
|
@ -19,7 +19,7 @@
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
import "../uav.js" as UAV
|
||||
import "../js/uav.js" as UAV
|
||||
|
||||
Item {
|
||||
id: sceneItem
|
||||
|
@ -19,8 +19,8 @@
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
import "../common.js" as Utils
|
||||
import "../uav.js" as UAV
|
||||
import "../js/common.js" as Utils
|
||||
import "../js/uav.js" as UAV
|
||||
|
||||
Item {
|
||||
id: info
|
||||
@ -62,7 +62,7 @@ Item {
|
||||
sceneSize: info.sceneSize
|
||||
elementName: "info-bg"
|
||||
width: parent.width
|
||||
opacity: pfdContext.terrainEnabled ? 0.3 : 1
|
||||
opacity: opaque ? 1 : 0.3
|
||||
}
|
||||
|
||||
//
|
||||
@ -452,7 +452,7 @@ Item {
|
||||
x: Math.floor(scaledBounds.x * sceneItem.width)
|
||||
y: Math.floor(scaledBounds.y * sceneItem.height)
|
||||
|
||||
opacity: pfdContext.terrainEnabled ? 0.6 : 1
|
||||
opacity: opaque ? 1 : 0.6
|
||||
|
||||
states: State {
|
||||
name: "fading"
|
||||
|
@ -19,8 +19,8 @@
|
||||
*/
|
||||
import QtQuick 2.0
|
||||
|
||||
import "../common.js" as Utils
|
||||
import "../uav.js" as UAV
|
||||
import "../js/common.js" as Utils
|
||||
import "../js/uav.js" as UAV
|
||||
|
||||
Item {
|
||||
id: panels
|
||||
|
@ -19,7 +19,7 @@
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
import "../uav.js" as UAV
|
||||
import "../js/uav.js" as UAV
|
||||
|
||||
Item {
|
||||
id: worldView
|
@ -22,50 +22,59 @@ import QtQuick 2.4
|
||||
import Pfd 1.0
|
||||
import OsgQtQuick 1.0
|
||||
|
||||
import "../common.js" as Utils
|
||||
import "../uav.js" as UAV
|
||||
import "../js/common.js" as Utils
|
||||
import "../js/uav.js" as UAV
|
||||
|
||||
OSGViewport {
|
||||
id: fullview
|
||||
id: osgViewport
|
||||
|
||||
//anchors.fill: parent
|
||||
focus: true
|
||||
sceneData: skyNode
|
||||
camera: camera
|
||||
|
||||
property real horizontCenter : horizontCenterItem.horizontCenter
|
||||
readonly property real horizontCenter : horizontCenterItem.horizontCenter
|
||||
|
||||
// Factor for OSGview vertical offset
|
||||
property double factor: 0.04
|
||||
// Factor for OSGViewer vertical offset
|
||||
readonly property double factor: 0.04
|
||||
|
||||
// Stretch height and apply offset
|
||||
//height: height * (1 + factor)
|
||||
y: -height * factor
|
||||
|
||||
sceneNode: skyNode
|
||||
camera: camera
|
||||
manipulator: geoTransformManipulator
|
||||
|
||||
OSGCamera {
|
||||
id: camera
|
||||
|
||||
fieldOfView: 100
|
||||
logarithmicDepthBuffer: true
|
||||
}
|
||||
|
||||
OSGGeoTransformManipulator {
|
||||
id: geoTransformManipulator
|
||||
|
||||
sceneNode: terrainFileNode
|
||||
clampToTerrain: true
|
||||
|
||||
attitude: UAV.attitude()
|
||||
position: UAV.position()
|
||||
}
|
||||
|
||||
OSGSkyNode {
|
||||
id: skyNode
|
||||
sceneData: terrainNode
|
||||
sceneNode: terrainFileNode
|
||||
viewport: osgViewport
|
||||
dateTime: Utils.getDateTime()
|
||||
minimumAmbientLight: pfdContext.minimumAmbientLight
|
||||
}
|
||||
|
||||
OSGFileNode {
|
||||
id: terrainNode
|
||||
id: terrainFileNode
|
||||
source: pfdContext.terrainFile
|
||||
async: false
|
||||
}
|
||||
|
||||
OSGCamera {
|
||||
id: camera
|
||||
fieldOfView: 100
|
||||
sceneNode: terrainNode
|
||||
logarithmicDepthBuffer: true
|
||||
clampToTerrain: true
|
||||
manipulatorMode: ManipulatorMode.User
|
||||
|
||||
attitude: UAV.attitude()
|
||||
position: UAV.position()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
// using rectangle instead of svg rendered to pixmap
|
||||
// as it's much more memory efficient
|
||||
@ -82,7 +91,6 @@ OSGViewport {
|
||||
|
||||
property double pitch1DegHeight: sceneItem.height * pitch1DegScaledHeight
|
||||
|
||||
|
||||
transform: [
|
||||
Translate {
|
||||
id: pitchTranslate
|
||||
@ -104,7 +112,7 @@ OSGViewport {
|
||||
property variant scaledBounds: svgRenderer.scaledElementBounds("pfd/pfd.svg", "pitch-window-terrain")
|
||||
|
||||
x: Math.floor(scaledBounds.x * sceneItem.width)
|
||||
y: Math.floor(scaledBounds.y * sceneItem.height) - fullview.y
|
||||
y: Math.floor(scaledBounds.y * sceneItem.height) - osgViewport.y
|
||||
width: Math.floor(scaledBounds.width * sceneItem.width)
|
||||
height: Math.floor(scaledBounds.height * sceneItem.height)
|
||||
|
127
ground/gcs/src/share/qml/pfd/PfdView.qml
Normal file
127
ground/gcs/src/share/qml/pfd/PfdView.qml
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The LibrePilot Project
|
||||
* Contact: http://www.librepilot.org
|
||||
*
|
||||
* This file is part of LibrePilot GCS.
|
||||
*
|
||||
* LibrePilot GCS 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.
|
||||
*
|
||||
* LibrePilot GCS 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 LibrePilot GCS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
Rectangle {
|
||||
|
||||
color: "#515151"
|
||||
|
||||
property string worldFile: "PfdSimpleWorld.qml"
|
||||
property bool opaque: true
|
||||
|
||||
SvgElementImage {
|
||||
id: background
|
||||
elementName: "pfd-window"
|
||||
fillMode: Image.PreserveAspectFit
|
||||
anchors.fill: parent
|
||||
sceneSize: Qt.size(width, height)
|
||||
|
||||
Rectangle {
|
||||
width: Math.floor(parent.paintedHeight * 1.319)
|
||||
height: Math.floor(parent.paintedHeight - parent.paintedHeight * 0.008)
|
||||
|
||||
color: "transparent"
|
||||
border.color: "white"
|
||||
border.width: Math.floor(parent.paintedHeight * 0.008)
|
||||
radius: Math.floor(parent.paintedHeight * 0.01)
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
Item {
|
||||
id: sceneItem
|
||||
|
||||
FontLoader {
|
||||
id: pt_bold
|
||||
source: "qrc:/utils/fonts/PTS75F.ttf"
|
||||
}
|
||||
|
||||
width: Math.floor((parent.paintedHeight * 1.32) - (parent.paintedHeight * 0.013))
|
||||
height: Math.floor(parent.paintedHeight - parent.paintedHeight * 0.02)
|
||||
property variant viewportSize : Qt.size(width, height)
|
||||
|
||||
anchors.centerIn: parent
|
||||
clip: true
|
||||
|
||||
Loader {
|
||||
id: worldLoader
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
source: worldFile
|
||||
}
|
||||
|
||||
HorizontCenter {
|
||||
id: horizontCenterItem
|
||||
sceneSize: sceneItem.viewportSize
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
RollScale {
|
||||
id: rollscale
|
||||
sceneSize: sceneItem.viewportSize
|
||||
horizontCenter: horizontCenterItem.horizontCenter
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
SvgElementImage {
|
||||
id: side_slip_fixed
|
||||
elementName: "sideslip-fixed"
|
||||
sceneSize: sceneItem.viewportSize
|
||||
|
||||
x: scaledBounds.x * sceneItem.width
|
||||
}
|
||||
|
||||
Compass {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
}
|
||||
|
||||
SpeedScale {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
}
|
||||
|
||||
AltitudeScale {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
}
|
||||
|
||||
VsiScale {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
visible: pfdContext.altitudeUnit != 0
|
||||
}
|
||||
|
||||
Info {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
}
|
||||
|
||||
Panels {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
}
|
||||
|
||||
Warnings {
|
||||
anchors.fill: parent
|
||||
sceneSize: sceneItem.viewportSize
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
import "../uav.js" as UAV
|
||||
import "../js/uav.js" as UAV
|
||||
|
||||
Item {
|
||||
id: sceneItem
|
||||
|
@ -19,7 +19,7 @@
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
import "../uav.js" as UAV
|
||||
import "../js/uav.js" as UAV
|
||||
|
||||
Item {
|
||||
id: sceneItem
|
||||
|
@ -19,7 +19,7 @@
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
import "../uav.js" as UAV
|
||||
import "../js/uav.js" as UAV
|
||||
|
||||
Item {
|
||||
id: sceneItem
|
||||
|
@ -19,8 +19,8 @@
|
||||
*/
|
||||
import QtQuick 2.4
|
||||
|
||||
import "../common.js" as Utils
|
||||
import "../uav.js" as UAV
|
||||
import "../js/common.js" as Utils
|
||||
import "../js/uav.js" as UAV
|
||||
|
||||
Item {
|
||||
id: warnings
|
||||
|
Loading…
Reference in New Issue
Block a user