Merged in f5soh/librepilot/update_credits (pull request #529)
[librepilot.git] / ground / gcs / src / libs / osgearth / osgQtQuick / OSGGeoTransformNode.cpp
blob092f5199de0306d2200abbf7e0c4127ac95bad8d
1 /**
2 ******************************************************************************
4 * @file OSGGeoTransformNode.cpp
5 * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
6 * @addtogroup
7 * @{
8 * @addtogroup
9 * @{
10 * @brief
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "OSGGeoTransformNode.hpp"
30 #include "utils/utility.h"
32 #include <osg/ComputeBoundsVisitor>
34 #include <osgEarth/GeoTransform>
35 #include <osgEarth/MapNode>
36 #include <osgEarth/GeoData>
38 #include <QDebug>
40 namespace osgQtQuick {
41 // NOTE : these flags should not overlap with OSGGroup flags!!!
42 // TODO : find a better way...
43 enum DirtyFlag { Scene = 1 << 10, Position = 1 << 11, Clamp = 1 << 12 };
45 struct OSGGeoTransformNode::Hidden : public QObject {
46 Q_OBJECT
48 private:
49 OSGGeoTransformNode * const self;
51 osg::ref_ptr<osgEarth::GeoTransform> transform;
53 public:
54 OSGNode *sceneNode;
56 float offset;
58 bool clampToTerrain;
59 bool intoTerrain;
61 QVector3D position;
63 Hidden(OSGGeoTransformNode *self) : QObject(self), self(self), sceneNode(NULL), offset(-1.0), clampToTerrain(false), intoTerrain(false)
66 osg::Node *createNode()
68 transform = new osgEarth::GeoTransform();
69 transform->setAutoRecomputeHeights(true);
70 return transform;
73 bool acceptSceneNode(OSGNode *node)
75 // qDebug() << "OSGGeoTransformNode::acceptSceneNode" << node;
76 if (sceneNode == node) {
77 return false;
80 if (sceneNode) {
81 disconnect(sceneNode);
84 sceneNode = node;
86 if (sceneNode) {
87 connect(sceneNode, &OSGNode::nodeChanged, this, &OSGGeoTransformNode::Hidden::onSceneNodeChanged);
90 return true;
93 void updateSceneNode()
95 // qDebug() << "OSGGeoTransformNode::updateSceneNode" << sceneNode;
96 if (sceneNode && sceneNode->node()) {
97 osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
98 if (mapNode) {
99 transform->setTerrain(mapNode->getTerrain());
100 } else {
101 qWarning() << "OSGGeoTransformNode::updateScene - scene data does not contain a map node";
106 void updatePosition()
108 // qDebug() << "OSGGeoTransformNode::updatePosition" << position;
110 osgEarth::MapNode *mapNode = NULL;
112 if (sceneNode && sceneNode->node()) {
113 mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
114 if (!mapNode) {
115 qWarning() << "OSGGeoTransformNode::updatePosition - scene node does not contain a map node";
117 } else {
118 qWarning() << "OSGGeoTransformNode::updatePosition - scene node is not valid";
120 if (mapNode) {
121 osgEarth::GeoPoint geoPoint = createGeoPoint(position, mapNode);
122 if (clampToTerrain) {
123 // get "size" of model
124 // TODO this should be done once only...
125 #if 0
126 osg::ComputeBoundsVisitor cbv;
127 transform->accept(cbv);
128 const osg::BoundingBox & bbox = cbv.getBoundingBox();
129 offset = bbox.radius();
130 #else
131 const osg::BoundingSphere & boundingSphere = transform->getBound();
132 offset = boundingSphere.radius();
133 #endif
134 // clamp model to terrain if needed
135 intoTerrain = clampGeoPoint(geoPoint, offset, mapNode);
136 if (intoTerrain) {
137 qDebug() << "OSGGeoTransformNode::updateNode - into terrain" << offset;
139 } else if (clampToTerrain) {
140 qWarning() << "OSGGeoTransformNode::onChildNodeChanged - cannot clamp without map node";
142 transform->setPosition(geoPoint);
146 private slots:
147 void onSceneNodeChanged(osg::Node *node)
149 // qDebug() << "OSGGeoTransformNode::onSceneNodeChanged" << node;
150 updateSceneNode();
151 updatePosition();
155 /* class OSGGeoTransformNode */
157 OSGGeoTransformNode::OSGGeoTransformNode(QObject *parent) : Inherited(parent), h(new Hidden(this))
160 OSGGeoTransformNode::~OSGGeoTransformNode()
162 delete h;
165 OSGNode *OSGGeoTransformNode::sceneNode() const
167 return h->sceneNode;
170 void OSGGeoTransformNode::setSceneNode(OSGNode *node)
172 if (h->acceptSceneNode(node)) {
173 setDirty(Scene);
174 emit sceneNodeChanged(node);
178 bool OSGGeoTransformNode::clampToTerrain() const
180 return h->clampToTerrain;
183 void OSGGeoTransformNode::setClampToTerrain(bool arg)
185 if (h->clampToTerrain != arg) {
186 h->clampToTerrain = arg;
187 setDirty(Clamp);
188 emit clampToTerrainChanged(clampToTerrain());
192 bool OSGGeoTransformNode::intoTerrain() const
194 return h->intoTerrain;
197 QVector3D OSGGeoTransformNode::position() const
199 return h->position;
202 void OSGGeoTransformNode::setPosition(QVector3D arg)
204 if (h->position != arg) {
205 h->position = arg;
206 setDirty(Position);
207 emit positionChanged(position());
211 osg::Node *OSGGeoTransformNode::createNode()
213 return h->createNode();
216 void OSGGeoTransformNode::updateNode()
218 Inherited::updateNode();
220 if (isDirty(Scene)) {
221 h->updateSceneNode();
223 if (isDirty(Clamp)) {
224 // do nothing...
226 if (isDirty(Scene | Clamp | Position)) {
227 h->updatePosition();
230 } // namespace osgQtQuick
232 #include "OSGGeoTransformNode.moc"