mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-19 04:52:12 +01:00
LP-29 replace OSGModelNode with more straightforward OSGGeoTransformNode
This commit is contained in:
parent
72d4d6a79b
commit
94b4d68400
302
ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp
Normal file
302
ground/gcs/src/libs/osgearth/osgQtQuick/OSGGeoTransformNode.cpp
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
*
|
||||||
|
* @file OSGTransformNode.cpp
|
||||||
|
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||||
|
* @addtogroup
|
||||||
|
* @{
|
||||||
|
* @addtogroup
|
||||||
|
* @{
|
||||||
|
* @brief
|
||||||
|
*****************************************************************************/
|
||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "OSGGeoTransformNode.hpp"
|
||||||
|
|
||||||
|
#include "../utility.h"
|
||||||
|
|
||||||
|
#include <osg/ComputeBoundsVisitor>
|
||||||
|
|
||||||
|
#include <osgearth/GeoTransform>
|
||||||
|
#include <osgEarth/MapNode>
|
||||||
|
#include <osgEarth/GeoData>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace osgQtQuick {
|
||||||
|
struct OSGGeoTransformNode::Hidden : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
struct NodeUpdateCallback : public osg::NodeCallback {
|
||||||
|
public:
|
||||||
|
NodeUpdateCallback(Hidden *h) : h(h) {}
|
||||||
|
|
||||||
|
void operator()(osg::Node *node, osg::NodeVisitor *nv);
|
||||||
|
|
||||||
|
mutable Hidden *h;
|
||||||
|
};
|
||||||
|
friend class NodeUpdateCallback;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Hidden(OSGGeoTransformNode *parent) : QObject(parent), self(parent), childNode(NULL), sceneNode(NULL), offset(-1.0), clampToTerrain(false), intoTerrain(false), dirty(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~Hidden()
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool acceptChildNode(OSGNode *node)
|
||||||
|
{
|
||||||
|
qDebug() << "OSGGeoTransformNode::acceptChildNode" << node;
|
||||||
|
if (childNode == node) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childNode) {
|
||||||
|
disconnect(childNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
childNode = node;
|
||||||
|
dirty = true;
|
||||||
|
|
||||||
|
if (childNode) {
|
||||||
|
connect(childNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onChildNodeChanged(osg::Node *)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool acceptSceneNode(OSGNode *node)
|
||||||
|
{
|
||||||
|
qDebug() << "OSGGeoTransformNode::acceptSceneNode" << node;
|
||||||
|
if (sceneNode == node) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sceneNode) {
|
||||||
|
disconnect(sceneNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
sceneNode = node;
|
||||||
|
dirty = true;
|
||||||
|
|
||||||
|
if (sceneNode) {
|
||||||
|
connect(sceneNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onSceneNodeChanged(osg::Node *)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateNode()
|
||||||
|
{
|
||||||
|
if (!dirty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dirty = false;
|
||||||
|
|
||||||
|
// qDebug() << "OSGGeoTransformNode::updateNode" << this;
|
||||||
|
|
||||||
|
osgEarth::GeoTransform *transform = getOrCreateTransform();
|
||||||
|
|
||||||
|
if (transform->getNumChildren() == 0) {
|
||||||
|
if (childNode && childNode->node()) {
|
||||||
|
transform->addChild(childNode->node());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (childNode && childNode->node()) {
|
||||||
|
if (transform->getChild(0) != childNode->node()) {
|
||||||
|
transform->removeChild(0, 1);
|
||||||
|
transform->addChild(childNode->node());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
transform->removeChild(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
osgEarth::MapNode *mapNode = NULL;
|
||||||
|
if (sceneNode && sceneNode->node()) {
|
||||||
|
mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
|
||||||
|
if (mapNode) {
|
||||||
|
transform->setTerrain(mapNode->getTerrain());
|
||||||
|
} else {
|
||||||
|
qWarning() << "OSGGeoTransformNode::updateNode - scene data does not contain a map node";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
osgEarth::GeoPoint geoPoint;
|
||||||
|
if (mapNode) {
|
||||||
|
geoPoint = osgQtQuick::toGeoPoint(mapNode->getTerrain()->getSRS(), position);
|
||||||
|
} else {
|
||||||
|
geoPoint = osgQtQuick::toGeoPoint(position);
|
||||||
|
}
|
||||||
|
if (clampToTerrain && mapNode) {
|
||||||
|
// get "size" of model
|
||||||
|
// TODO this should be done once only...
|
||||||
|
osg::ComputeBoundsVisitor cbv;
|
||||||
|
childNode->node()->accept(cbv);
|
||||||
|
const osg::BoundingBox & bbox = cbv.getBoundingBox();
|
||||||
|
offset = bbox.radius();
|
||||||
|
|
||||||
|
// qDebug() << "OSGGeoTransformNode::updateNode - offset" << offset;
|
||||||
|
|
||||||
|
// clamp model to terrain if needed
|
||||||
|
intoTerrain = clampGeoPoint(geoPoint, offset, mapNode);
|
||||||
|
}
|
||||||
|
transform->setPosition(geoPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
osgEarth::GeoTransform *getOrCreateTransform()
|
||||||
|
{
|
||||||
|
if (transform.valid()) {
|
||||||
|
return transform.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
transform = new osgEarth::GeoTransform();
|
||||||
|
transform->setAutoRecomputeHeights(true);
|
||||||
|
|
||||||
|
transform->addUpdateCallback(new NodeUpdateCallback(this));
|
||||||
|
|
||||||
|
self->setNode(transform);
|
||||||
|
|
||||||
|
return transform.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
OSGGeoTransformNode *const self;
|
||||||
|
|
||||||
|
OSGNode *childNode;
|
||||||
|
OSGNode *sceneNode;
|
||||||
|
|
||||||
|
osg::ref_ptr<osgEarth::GeoTransform> transform;
|
||||||
|
|
||||||
|
float offset;
|
||||||
|
|
||||||
|
bool clampToTerrain;
|
||||||
|
bool intoTerrain;
|
||||||
|
|
||||||
|
QVector3D position;
|
||||||
|
|
||||||
|
bool dirty;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void onChildNodeChanged(osg::Node *node)
|
||||||
|
{
|
||||||
|
qDebug() << "OSGGeoTransformNode::onChildNodeChanged" << node;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSceneNodeChanged(osg::Node *node)
|
||||||
|
{
|
||||||
|
qDebug() << "OSGGeoTransformNode::onSceneNodeChanged" << node;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* struct Hidden::NodeUpdateCallback */
|
||||||
|
|
||||||
|
void OSGGeoTransformNode::Hidden::NodeUpdateCallback::operator()(osg::Node *node, osg::NodeVisitor *nv)
|
||||||
|
{
|
||||||
|
nv->traverse(*node);
|
||||||
|
h->updateNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
OSGGeoTransformNode::OSGGeoTransformNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
|
||||||
|
{
|
||||||
|
qDebug() << "OSGGeoTransformNode::OSGGeoTransformNode";
|
||||||
|
}
|
||||||
|
|
||||||
|
OSGGeoTransformNode::~OSGGeoTransformNode()
|
||||||
|
{
|
||||||
|
qDebug() << "OSGGeoTransformNode::~OSGGeoTransformNode";
|
||||||
|
}
|
||||||
|
|
||||||
|
OSGNode *OSGGeoTransformNode::modelData()
|
||||||
|
{
|
||||||
|
return h->childNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSGGeoTransformNode::setModelData(OSGNode *node)
|
||||||
|
{
|
||||||
|
if (h->acceptChildNode(node)) {
|
||||||
|
emit modelDataChanged(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OSGNode *OSGGeoTransformNode::sceneData()
|
||||||
|
{
|
||||||
|
return h->sceneNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSGGeoTransformNode::setSceneData(OSGNode *node)
|
||||||
|
{
|
||||||
|
if (h->acceptSceneNode(node)) {
|
||||||
|
emit sceneDataChanged(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OSGGeoTransformNode::clampToTerrain() const
|
||||||
|
{
|
||||||
|
return h->clampToTerrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSGGeoTransformNode::setClampToTerrain(bool arg)
|
||||||
|
{
|
||||||
|
if (h->clampToTerrain != arg) {
|
||||||
|
h->clampToTerrain = arg;
|
||||||
|
h->dirty = true;
|
||||||
|
emit clampToTerrainChanged(clampToTerrain());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OSGGeoTransformNode::intoTerrain() const
|
||||||
|
{
|
||||||
|
return h->intoTerrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector3D OSGGeoTransformNode::position() const
|
||||||
|
{
|
||||||
|
return h->position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSGGeoTransformNode::setPosition(QVector3D arg)
|
||||||
|
{
|
||||||
|
if (h->position != arg) {
|
||||||
|
h->position = arg;
|
||||||
|
h->dirty = true;
|
||||||
|
emit positionChanged(position());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSGGeoTransformNode::attach(osgViewer::View *view)
|
||||||
|
{
|
||||||
|
// qDebug() << "OSGGeoTransformNode::attach " << view;
|
||||||
|
if (h->childNode) {
|
||||||
|
h->childNode->attach(view);
|
||||||
|
}
|
||||||
|
h->updateNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSGGeoTransformNode::detach(osgViewer::View *view)
|
||||||
|
{
|
||||||
|
// qDebug() << "OSGGeoTransformNode::detach " << view;
|
||||||
|
if (h->childNode) {
|
||||||
|
h->childNode->detach(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace osgQtQuick
|
||||||
|
|
||||||
|
#include "OSGGeoTransformNode.moc"
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*
|
*
|
||||||
* @file OSGModelNode.hpp
|
* @file OSGTransformNode.hpp
|
||||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||||
* @addtogroup
|
* @addtogroup
|
||||||
* @{
|
* @{
|
||||||
@ -25,35 +25,31 @@
|
|||||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _H_OSGQTQUICK_MODELNODE_H_
|
#ifndef _H_OSGQTQUICK_GEOTRANSFORMNODE_H_
|
||||||
#define _H_OSGQTQUICK_MODELNODE_H_
|
#define _H_OSGQTQUICK_GEOTRANSFORMNODE_H_
|
||||||
|
|
||||||
#include "Export.hpp"
|
#include "Export.hpp"
|
||||||
#include "OSGNode.hpp"
|
#include "OSGNode.hpp"
|
||||||
|
|
||||||
#include <QVector3D>
|
#include <QVector3D>
|
||||||
#include <QUrl>
|
|
||||||
|
|
||||||
namespace osgViewer {
|
|
||||||
class View;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// TODO derive from OSGGroup...
|
||||||
namespace osgQtQuick {
|
namespace osgQtQuick {
|
||||||
class OSGQTQUICK_EXPORT OSGModelNode : public OSGNode {
|
class OSGQTQUICK_EXPORT OSGGeoTransformNode : public OSGNode {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
// TODO rename to parentNode and modelNode
|
// TODO rename to childNode
|
||||||
Q_PROPERTY(osgQtQuick::OSGNode *modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
|
Q_PROPERTY(osgQtQuick::OSGNode *modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
|
||||||
|
// TODO rename to sceneNode
|
||||||
Q_PROPERTY(osgQtQuick::OSGNode * sceneData READ sceneData WRITE setSceneData NOTIFY sceneDataChanged)
|
Q_PROPERTY(osgQtQuick::OSGNode * sceneData READ sceneData WRITE setSceneData NOTIFY sceneDataChanged)
|
||||||
|
|
||||||
Q_PROPERTY(bool clampToTerrain READ clampToTerrain WRITE setClampToTerrain NOTIFY clampToTerrainChanged)
|
Q_PROPERTY(bool clampToTerrain READ clampToTerrain WRITE setClampToTerrain NOTIFY clampToTerrainChanged)
|
||||||
Q_PROPERTY(bool intoTerrain READ intoTerrain NOTIFY intoTerrainChanged)
|
Q_PROPERTY(bool intoTerrain READ intoTerrain NOTIFY intoTerrainChanged)
|
||||||
|
|
||||||
Q_PROPERTY(QVector3D attitude READ attitude WRITE setAttitude NOTIFY attitudeChanged)
|
|
||||||
Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged)
|
Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OSGModelNode(QObject *parent = 0);
|
OSGGeoTransformNode(QObject *parent = 0);
|
||||||
virtual ~OSGModelNode();
|
virtual ~OSGGeoTransformNode();
|
||||||
|
|
||||||
OSGNode *modelData();
|
OSGNode *modelData();
|
||||||
void setModelData(OSGNode *node);
|
void setModelData(OSGNode *node);
|
||||||
@ -66,9 +62,6 @@ public:
|
|||||||
|
|
||||||
bool intoTerrain() const;
|
bool intoTerrain() const;
|
||||||
|
|
||||||
QVector3D attitude() const;
|
|
||||||
void setAttitude(QVector3D arg);
|
|
||||||
|
|
||||||
QVector3D position() const;
|
QVector3D position() const;
|
||||||
void setPosition(QVector3D arg);
|
void setPosition(QVector3D arg);
|
||||||
|
|
||||||
@ -77,12 +70,12 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void modelDataChanged(OSGNode *node);
|
void modelDataChanged(OSGNode *node);
|
||||||
|
|
||||||
void sceneDataChanged(OSGNode *node);
|
void sceneDataChanged(OSGNode *node);
|
||||||
|
|
||||||
void clampToTerrainChanged(bool arg);
|
void clampToTerrainChanged(bool arg);
|
||||||
void intoTerrainChanged(bool arg);
|
void intoTerrainChanged(bool arg);
|
||||||
|
|
||||||
void attitudeChanged(QVector3D arg);
|
|
||||||
void positionChanged(QVector3D arg);
|
void positionChanged(QVector3D arg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -91,4 +84,4 @@ private:
|
|||||||
};
|
};
|
||||||
} // namespace osgQtQuick
|
} // namespace osgQtQuick
|
||||||
|
|
||||||
#endif // _H_OSGQTQUICK_MODELNODE_H_
|
#endif // _H_OSGQTQUICK_GEOTRANSFORMNODE_H_
|
@ -1,367 +0,0 @@
|
|||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
*
|
|
||||||
* @file OSGModelNode.cpp
|
|
||||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
|
||||||
* @addtogroup
|
|
||||||
* @{
|
|
||||||
* @addtogroup
|
|
||||||
* @{
|
|
||||||
* @brief
|
|
||||||
*****************************************************************************/
|
|
||||||
/*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "OSGModelNode.hpp"
|
|
||||||
|
|
||||||
#include "../utility.h"
|
|
||||||
|
|
||||||
#include <osg/Quat>
|
|
||||||
#include <osg/ComputeBoundsVisitor>
|
|
||||||
#include <osgViewer/View>
|
|
||||||
|
|
||||||
#include <osgEarth/MapNode>
|
|
||||||
#include <osgEarth/GeoData>
|
|
||||||
|
|
||||||
#include <osgEarthSymbology/Style>
|
|
||||||
#include <osgEarthSymbology/ModelSymbol>
|
|
||||||
|
|
||||||
#include <osgEarthAnnotation/ModelNode>
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
namespace osgQtQuick {
|
|
||||||
struct OSGModelNode::Hidden : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
struct NodeUpdateCallback : public osg::NodeCallback {
|
|
||||||
public:
|
|
||||||
NodeUpdateCallback(Hidden *h) : h(h) {}
|
|
||||||
|
|
||||||
void operator()(osg::Node *node, osg::NodeVisitor *nv);
|
|
||||||
|
|
||||||
mutable Hidden *h;
|
|
||||||
};
|
|
||||||
friend class NodeUpdateCallback;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Hidden(OSGModelNode *parent) : QObject(parent), self(parent), modelData(NULL), sceneData(NULL), offset(-1.0), clampToTerrain(false), intoTerrain(false), dirty(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
~Hidden()
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool acceptModelData(OSGNode *node)
|
|
||||||
{
|
|
||||||
qDebug() << "OSGModelNode::acceptModelData" << node;
|
|
||||||
if (modelData == node) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modelData) {
|
|
||||||
disconnect(modelData);
|
|
||||||
}
|
|
||||||
|
|
||||||
modelData = node;
|
|
||||||
|
|
||||||
if (modelData) {
|
|
||||||
acceptModelNode(modelData->node());
|
|
||||||
connect(modelData, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onModelNodeChanged(osg::Node *)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool acceptModelNode(osg::Node *node)
|
|
||||||
{
|
|
||||||
qDebug() << "OSGModelNode::acceptModelNode" << node;
|
|
||||||
if (!node) {
|
|
||||||
qWarning() << "OSGModelNode::acceptModelNode - node is null";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sceneData || !sceneData->node()) {
|
|
||||||
qWarning() << "OSGModelNode::acceptModelNode - no scene data";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneData->node());
|
|
||||||
if (!mapNode) {
|
|
||||||
qWarning() << "OSGModelNode::acceptModelNode - scene data does not contain a map node";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// establish the coordinate system we wish to use:
|
|
||||||
// const osgEarth::SpatialReference* latLong = osgEarth::SpatialReference::get("wgs84");
|
|
||||||
|
|
||||||
osgEarth::Symbology::Style style;
|
|
||||||
|
|
||||||
// construct the symbology
|
|
||||||
osgEarth::Symbology::ModelSymbol *modelSymbol = style.getOrCreate<osgEarth::Symbology::ModelSymbol>();
|
|
||||||
modelSymbol->setModel(node);
|
|
||||||
|
|
||||||
// create ModelNode
|
|
||||||
modelNode = new osgEarth::Annotation::ModelNode(mapNode, style);
|
|
||||||
|
|
||||||
// add update callback
|
|
||||||
if (!nodeUpdateCallback.valid()) {
|
|
||||||
nodeUpdateCallback = new NodeUpdateCallback(this);
|
|
||||||
}
|
|
||||||
modelNode->addUpdateCallback(nodeUpdateCallback.get());
|
|
||||||
|
|
||||||
self->setNode(modelNode);
|
|
||||||
|
|
||||||
dirty = true;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool acceptSceneData(OSGNode *node)
|
|
||||||
{
|
|
||||||
qDebug() << "OSGModelNode::acceptSceneData" << node;
|
|
||||||
if (sceneData == node) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sceneData) {
|
|
||||||
disconnect(sceneData);
|
|
||||||
}
|
|
||||||
|
|
||||||
sceneData = node;
|
|
||||||
|
|
||||||
if (sceneData) {
|
|
||||||
// TODO find a better way
|
|
||||||
if (modelData && modelData->node()) {
|
|
||||||
acceptModelNode(modelData->node());
|
|
||||||
}
|
|
||||||
connect(sceneData, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onSceneNodeChanged(osg::Node *)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO model update gets jitter if camera is thrown (i.e animated)
|
|
||||||
void updateNode()
|
|
||||||
{
|
|
||||||
if (!dirty || !modelNode.valid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dirty = false;
|
|
||||||
|
|
||||||
osgEarth::GeoPoint geoPoint = osgQtQuick::toGeoPoint(position);
|
|
||||||
if (clampToTerrain) {
|
|
||||||
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneData->node());
|
|
||||||
if (mapNode) {
|
|
||||||
// get "size" of model
|
|
||||||
// TODO this should be done once only...
|
|
||||||
osg::ComputeBoundsVisitor cbv;
|
|
||||||
modelNode->accept(cbv);
|
|
||||||
const osg::BoundingBox & bbox = cbv.getBoundingBox();
|
|
||||||
offset = bbox.radius();
|
|
||||||
|
|
||||||
// clamp model to terrain if needed
|
|
||||||
intoTerrain = clampGeoPoint(geoPoint, offset, mapNode);
|
|
||||||
} else {
|
|
||||||
qWarning() << "OSGModelNode::updateNode - scene data does not contain a map node";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
modelNode->setPosition(geoPoint);
|
|
||||||
modelNode->setLocalRotation(localRotation());
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Quat localRotation()
|
|
||||||
{
|
|
||||||
double roll = osg::DegreesToRadians(attitude.x());
|
|
||||||
double pitch = osg::DegreesToRadians(attitude.y());
|
|
||||||
double yaw = osg::DegreesToRadians(attitude.z());
|
|
||||||
osg::Quat q = osg::Quat(
|
|
||||||
roll, osg::Vec3d(0, 1, 0),
|
|
||||||
pitch, osg::Vec3d(1, 0, 0),
|
|
||||||
yaw, osg::Vec3d(0, 0, -1));
|
|
||||||
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSGModelNode *const self;
|
|
||||||
|
|
||||||
OSGNode *modelData;
|
|
||||||
OSGNode *sceneData;
|
|
||||||
|
|
||||||
osg::ref_ptr<osgEarth::Annotation::ModelNode> modelNode;
|
|
||||||
|
|
||||||
float offset;
|
|
||||||
|
|
||||||
bool clampToTerrain;
|
|
||||||
bool intoTerrain;
|
|
||||||
|
|
||||||
QVector3D attitude;
|
|
||||||
QVector3D position;
|
|
||||||
|
|
||||||
// handle attitude/position/etc independently
|
|
||||||
bool dirty;
|
|
||||||
|
|
||||||
osg::observer_ptr<NodeUpdateCallback> nodeUpdateCallback;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
|
|
||||||
void onModelNodeChanged(osg::Node *node)
|
|
||||||
{
|
|
||||||
qDebug() << "OSGModelNode::onModelNodeChanged" << node;
|
|
||||||
if (modelData) {
|
|
||||||
if (modelNode.valid()) {
|
|
||||||
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneData->node());
|
|
||||||
if (mapNode) {
|
|
||||||
mapNode->removeChild(modelNode);
|
|
||||||
}
|
|
||||||
if (nodeUpdateCallback.valid()) {
|
|
||||||
modelNode->removeUpdateCallback(nodeUpdateCallback.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (node) {
|
|
||||||
acceptModelNode(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void onSceneNodeChanged(osg::Node *node)
|
|
||||||
{
|
|
||||||
qDebug() << "OSGModelNode::onSceneNodeChanged" << node;
|
|
||||||
// TODO needs to be improved...
|
|
||||||
if (modelData) {
|
|
||||||
if (modelNode.valid()) {
|
|
||||||
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneData->node());
|
|
||||||
if (mapNode) {
|
|
||||||
mapNode->removeChild(modelNode);
|
|
||||||
}
|
|
||||||
if (nodeUpdateCallback.valid()) {
|
|
||||||
modelNode->removeUpdateCallback(nodeUpdateCallback.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (modelData->node()) {
|
|
||||||
acceptModelNode(modelData->node());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* struct Hidden::NodeUpdateCallback */
|
|
||||||
|
|
||||||
void OSGModelNode::Hidden::NodeUpdateCallback::operator()(osg::Node *node, osg::NodeVisitor *nv)
|
|
||||||
{
|
|
||||||
h->updateNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
OSGModelNode::OSGModelNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
|
|
||||||
{
|
|
||||||
qDebug() << "OSGModelNode::OSGModelNode";
|
|
||||||
}
|
|
||||||
|
|
||||||
OSGModelNode::~OSGModelNode()
|
|
||||||
{
|
|
||||||
qDebug() << "OSGModelNode::~OSGModelNode";
|
|
||||||
}
|
|
||||||
|
|
||||||
OSGNode *OSGModelNode::modelData()
|
|
||||||
{
|
|
||||||
return h->modelData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSGModelNode::setModelData(OSGNode *node)
|
|
||||||
{
|
|
||||||
if (h->acceptModelData(node)) {
|
|
||||||
emit modelDataChanged(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OSGNode *OSGModelNode::sceneData()
|
|
||||||
{
|
|
||||||
return h->sceneData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSGModelNode::setSceneData(OSGNode *node)
|
|
||||||
{
|
|
||||||
if (h->acceptSceneData(node)) {
|
|
||||||
emit sceneDataChanged(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OSGModelNode::clampToTerrain() const
|
|
||||||
{
|
|
||||||
return h->clampToTerrain;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSGModelNode::setClampToTerrain(bool arg)
|
|
||||||
{
|
|
||||||
if (h->clampToTerrain != arg) {
|
|
||||||
h->clampToTerrain = arg;
|
|
||||||
h->dirty = true;
|
|
||||||
emit clampToTerrainChanged(clampToTerrain());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OSGModelNode::intoTerrain() const
|
|
||||||
{
|
|
||||||
return h->intoTerrain;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector3D OSGModelNode::attitude() const
|
|
||||||
{
|
|
||||||
return h->attitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSGModelNode::setAttitude(QVector3D arg)
|
|
||||||
{
|
|
||||||
if (h->attitude != arg) {
|
|
||||||
h->attitude = arg;
|
|
||||||
h->dirty = true;
|
|
||||||
emit attitudeChanged(attitude());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector3D OSGModelNode::position() const
|
|
||||||
{
|
|
||||||
return h->position;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSGModelNode::setPosition(QVector3D arg)
|
|
||||||
{
|
|
||||||
if (h->position != arg) {
|
|
||||||
h->position = arg;
|
|
||||||
h->dirty = true;
|
|
||||||
emit positionChanged(position());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSGModelNode::attach(osgViewer::View *view)
|
|
||||||
{
|
|
||||||
// qDebug() << "OSGModelNode::attach " << view;
|
|
||||||
if (h->modelData) {
|
|
||||||
h->modelData->attach(view);
|
|
||||||
}
|
|
||||||
h->updateNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSGModelNode::detach(osgViewer::View *view)
|
|
||||||
{
|
|
||||||
// qDebug() << "OSGModelNode::detach " << view;
|
|
||||||
if (h->modelData) {
|
|
||||||
h->modelData->detach(view);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace osgQtQuick
|
|
||||||
|
|
||||||
#include "OSGModelNode.moc"
|
|
@ -58,10 +58,8 @@ void OSGNode::setNode(osg::Node *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OSGNode::attach(osgViewer::View *view)
|
void OSGNode::attach(osgViewer::View *view)
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
void OSGNode::detach(osgViewer::View *view)
|
void OSGNode::detach(osgViewer::View *view)
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
} // namespace osgQtQuick
|
} // namespace osgQtQuick
|
||||||
|
@ -41,7 +41,6 @@ class View;
|
|||||||
} // namespace osgViewer
|
} // namespace osgViewer
|
||||||
|
|
||||||
namespace osgQtQuick {
|
namespace osgQtQuick {
|
||||||
|
|
||||||
class OSGQTQUICK_EXPORT OSGNode : public QObject {
|
class OSGQTQUICK_EXPORT OSGNode : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
childNode = node;
|
childNode = node;
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
|
||||||
if (childNode) {
|
if (childNode) {
|
||||||
connect(childNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onChildNodeChanged(osg::Node *)));
|
connect(childNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onChildNodeChanged(osg::Node *)));
|
||||||
@ -91,15 +91,13 @@ public:
|
|||||||
if (childNode && childNode->node()) {
|
if (childNode && childNode->node()) {
|
||||||
transform->addChild(childNode->node());
|
transform->addChild(childNode->node());
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (childNode && childNode->node()) {
|
if (childNode && childNode->node()) {
|
||||||
if (transform->getChild(0) != childNode->node()) {
|
if (transform->getChild(0) != childNode->node()) {
|
||||||
transform->removeChild(0, 1);
|
transform->removeChild(0, 1);
|
||||||
transform->addChild(childNode->node());
|
transform->addChild(childNode->node());
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
transform->removeChild(0, 1);
|
transform->removeChild(0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ public:
|
|||||||
qDebug() << "OSGViewport::attach - found map node" << mapNode;
|
qDebug() << "OSGViewport::attach - found map node" << mapNode;
|
||||||
|
|
||||||
// remove light to prevent unnecessary state changes in SceneView
|
// remove light to prevent unnecessary state changes in SceneView
|
||||||
// scene will get light from sky
|
// scene will get light from sky (works only with latest > 2.7)
|
||||||
// view->setLightingMode(osg::View::NO_LIGHT);
|
// view->setLightingMode(osg::View::NO_LIGHT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -70,11 +70,11 @@ SOURCES += \
|
|||||||
osgQtQuick/OSGViewport.cpp
|
osgQtQuick/OSGViewport.cpp
|
||||||
|
|
||||||
osgearth:HEADERS += \
|
osgearth:HEADERS += \
|
||||||
osgQtQuick/OSGModelNode.hpp \
|
osgQtQuick/OSGSkyNode.hpp \
|
||||||
osgQtQuick/OSGSkyNode.hpp
|
osgQtQuick/OSGGeoTransformNode.hpp
|
||||||
|
|
||||||
osgearth:SOURCES += \
|
osgearth:SOURCES += \
|
||||||
osgQtQuick/OSGModelNode.cpp \
|
osgQtQuick/OSGSkyNode.cpp \
|
||||||
osgQtQuick/OSGSkyNode.cpp
|
osgQtQuick/OSGGeoTransformNode.cpp
|
||||||
|
|
||||||
copy_osg:include(copydata.pro)
|
copy_osg:include(copydata.pro)
|
||||||
|
@ -34,9 +34,7 @@
|
|||||||
#include "osgQtQuick/OSGTransformNode.hpp"
|
#include "osgQtQuick/OSGTransformNode.hpp"
|
||||||
#include "osgQtQuick/OSGShapeNode.hpp"
|
#include "osgQtQuick/OSGShapeNode.hpp"
|
||||||
#include "osgQtQuick/OSGTextNode.hpp"
|
#include "osgQtQuick/OSGTextNode.hpp"
|
||||||
#include "osgQtQuick/OSGModelNode.hpp"
|
|
||||||
#include "osgQtQuick/OSGBackgroundNode.hpp"
|
#include "osgQtQuick/OSGBackgroundNode.hpp"
|
||||||
#include "osgQtQuick/OSGSkyNode.hpp"
|
|
||||||
#include "osgQtQuick/OSGCamera.hpp"
|
#include "osgQtQuick/OSGCamera.hpp"
|
||||||
#include "osgQtQuick/OSGViewport.hpp"
|
#include "osgQtQuick/OSGViewport.hpp"
|
||||||
|
|
||||||
@ -60,6 +58,9 @@
|
|||||||
#endif // USE_OSG_QT
|
#endif // USE_OSG_QT
|
||||||
|
|
||||||
#ifdef USE_OSGEARTH
|
#ifdef USE_OSGEARTH
|
||||||
|
#include "osgQtQuick/OSGSkyNode.hpp"
|
||||||
|
#include "osgQtQuick/OSGGeoTransformNode.hpp"
|
||||||
|
|
||||||
#include <osgEarth/Capabilities>
|
#include <osgEarth/Capabilities>
|
||||||
#include <osgEarth/MapNode>
|
#include <osgEarth/MapNode>
|
||||||
#include <osgEarth/SpatialReference>
|
#include <osgEarth/SpatialReference>
|
||||||
@ -440,12 +441,15 @@ QString getUsageString(osgViewer::CompositeViewer *viewer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_OSGEARTH
|
#ifdef USE_OSGEARTH
|
||||||
|
osgEarth::GeoPoint toGeoPoint(const osgEarth::SpatialReference *srs, const QVector3D &position)
|
||||||
|
{
|
||||||
|
osgEarth::GeoPoint geoPoint(srs, position.x(), position.y(), position.z(), osgEarth::ALTMODE_ABSOLUTE);
|
||||||
|
return geoPoint;
|
||||||
|
}
|
||||||
|
|
||||||
osgEarth::GeoPoint toGeoPoint(const QVector3D &position)
|
osgEarth::GeoPoint toGeoPoint(const QVector3D &position)
|
||||||
{
|
{
|
||||||
osgEarth::GeoPoint geoPoint(osgEarth::SpatialReference::get("wgs84"),
|
return toGeoPoint(osgEarth::SpatialReference::get("wgs84"), position);
|
||||||
position.x(), position.y(), position.z(), osgEarth::ALTMODE_ABSOLUTE);
|
|
||||||
|
|
||||||
return geoPoint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool clampGeoPoint(osgEarth::GeoPoint &geoPoint, float offset, osgEarth::MapNode *mapNode)
|
bool clampGeoPoint(osgEarth::GeoPoint &geoPoint, float offset, osgEarth::MapNode *mapNode)
|
||||||
@ -542,8 +546,8 @@ void registerTypes()
|
|||||||
qmlRegisterType<osgQtQuick::TrackerMode>("OsgQtQuick", maj, min, "TrackerMode");
|
qmlRegisterType<osgQtQuick::TrackerMode>("OsgQtQuick", maj, min, "TrackerMode");
|
||||||
|
|
||||||
#ifdef USE_OSGEARTH
|
#ifdef USE_OSGEARTH
|
||||||
qmlRegisterType<osgQtQuick::OSGModelNode>("OsgQtQuick", maj, min, "OSGModelNode");
|
|
||||||
qmlRegisterType<osgQtQuick::OSGSkyNode>("OsgQtQuick", maj, min, "OSGSkyNode");
|
qmlRegisterType<osgQtQuick::OSGSkyNode>("OsgQtQuick", maj, min, "OSGSkyNode");
|
||||||
|
qmlRegisterType<osgQtQuick::OSGGeoTransformNode>("OsgQtQuick", maj, min, "OSGGeoTransformNode");
|
||||||
#endif // USE_OSGEARTH
|
#endif // USE_OSGEARTH
|
||||||
}
|
}
|
||||||
} // namespace osgQtQuick
|
} // namespace osgQtQuick
|
||||||
|
@ -62,6 +62,7 @@ namespace osgEarth {
|
|||||||
class Capabilities;
|
class Capabilities;
|
||||||
class GeoPoint;
|
class GeoPoint;
|
||||||
class MapNode;
|
class MapNode;
|
||||||
|
class SpatialReference;
|
||||||
} // namespace osgEarth
|
} // namespace osgEarth
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -145,6 +146,7 @@ QString getUsageString(osgViewer::CompositeViewer *viewer);
|
|||||||
|
|
||||||
#ifdef USE_OSGEARTH
|
#ifdef USE_OSGEARTH
|
||||||
osgEarth::GeoPoint toGeoPoint(const QVector3D &position);
|
osgEarth::GeoPoint toGeoPoint(const QVector3D &position);
|
||||||
|
osgEarth::GeoPoint toGeoPoint(const osgEarth::SpatialReference *srs, const QVector3D &position);
|
||||||
bool clampGeoPoint(osgEarth::GeoPoint &geoPoint, float offset, osgEarth::MapNode *mapNode);
|
bool clampGeoPoint(osgEarth::GeoPoint &geoPoint, float offset, osgEarth::MapNode *mapNode);
|
||||||
void capabilitiesInfo(const osgEarth::Capabilities & caps);
|
void capabilitiesInfo(const osgEarth::Capabilities & caps);
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,13 +49,14 @@ OSGViewport {
|
|||||||
async: false
|
async: false
|
||||||
}
|
}
|
||||||
|
|
||||||
OSGModelNode {
|
OSGGeoTransformNode {
|
||||||
id: modelNode
|
id: modelNode
|
||||||
clampToTerrain: true
|
|
||||||
modelData: modelTransformNode
|
modelData: modelTransformNode
|
||||||
sceneData: terrainNode
|
sceneData: terrainNode
|
||||||
|
|
||||||
attitude: UAV.attitude()
|
clampToTerrain: true
|
||||||
|
|
||||||
position: UAV.position()
|
position: UAV.position()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,11 +65,16 @@ OSGViewport {
|
|||||||
modelData: modelFileNode
|
modelData: modelFileNode
|
||||||
// model dimensions are in mm, scale to meters
|
// model dimensions are in mm, scale to meters
|
||||||
scale: Qt.vector3d(0.001, 0.001, 0.001)
|
scale: Qt.vector3d(0.001, 0.001, 0.001)
|
||||||
|
attitude: UAV.attitude()
|
||||||
}
|
}
|
||||||
|
|
||||||
OSGFileNode {
|
OSGFileNode {
|
||||||
id: modelFileNode
|
id: modelFileNode
|
||||||
source: pfdContext.modelFile
|
|
||||||
|
// use ShaderGen pseudoloader to generate the shaders expected by osgEarth
|
||||||
|
// see http://docs.osgearth.org/en/latest/faq.html#i-added-a-node-but-it-has-no-texture-lighting-etc-in-osgearth-why
|
||||||
|
source: pfdContext.modelFile + ".osgearth_shadergen"
|
||||||
|
|
||||||
async: false
|
async: false
|
||||||
optimizeMode: OptimizeMode.OptimizeAndCheck
|
optimizeMode: OptimizeMode.OptimizeAndCheck
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user