1
0
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:
Lalanne Laurent 2016-04-14 22:14:59 +02:00
commit 23f1867746
75 changed files with 3094 additions and 1816 deletions

View 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

View 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_

View File

@ -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

View File

@ -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"

View 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"

View 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_

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View 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"

View File

@ -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_

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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_

View File

@ -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"

View File

@ -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_

View File

@ -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"

View File

@ -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_

View File

@ -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"

View File

@ -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_

View File

@ -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"

View File

@ -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_

View File

@ -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()

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -1,4 +1,4 @@
#include "shapeutils.h"
#include "utils/shapeutils.h"
#include <math.h>

View File

@ -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

View File

@ -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

View File

@ -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();
}

View File

@ -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);
}
}

View 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_ */

View File

@ -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.

View File

@ -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>

View File

@ -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
}
}

View File

@ -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 {
}

View 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 {
}

View File

@ -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"
}

View 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"
}

View File

@ -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];
}

View File

@ -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
}
}

View File

@ -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();
}
}

View File

@ -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

View File

@ -19,7 +19,7 @@
*/
import QtQuick 2.4
import "../uav.js" as UAV
import "../js/uav.js" as UAV
Item {
id: sceneItem

View File

@ -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"

View File

@ -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

View File

@ -19,7 +19,7 @@
*/
import QtQuick 2.4
import "../uav.js" as UAV
import "../js/uav.js" as UAV
Item {
id: worldView

View File

@ -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)

View 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
}
}
}
}

View File

@ -19,7 +19,7 @@
*/
import QtQuick 2.4
import "../uav.js" as UAV
import "../js/uav.js" as UAV
Item {
id: sceneItem

View File

@ -19,7 +19,7 @@
*/
import QtQuick 2.4
import "../uav.js" as UAV
import "../js/uav.js" as UAV
Item {
id: sceneItem

View File

@ -19,7 +19,7 @@
*/
import QtQuick 2.4
import "../uav.js" as UAV
import "../js/uav.js" as UAV
Item {
id: sceneItem

View File

@ -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