1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-30 15:52:12 +01:00

LP-29 made code more consistent w/r to dirty handling, etc...

This commit is contained in:
Philippe Renon 2016-03-10 21:14:01 +01:00
parent 7c21a09b7f
commit 6c82a7f01a
21 changed files with 709 additions and 508 deletions

View File

@ -38,30 +38,20 @@ namespace osgQtQuick {
struct OSGBackgroundNode::Hidden : public QObject {
Q_OBJECT
private:
OSGBackgroundNode * const self;
public:
QUrl url;
Hidden(OSGBackgroundNode *parent) : QObject(parent), self(parent), url() {}
bool acceptImageFile(QUrl url)
void updateNode()
{
// qDebug() << "OSGBackgroundNode::acceptImageFile" << url;
if (this->url == url) {
return false;
}
this->url = url;
realize();
return true;
}
void realize()
{
qDebug() << "OSGBackgroundNode::realize";
// qDebug() << "OSGBackgroundNode::realize - reading image file" << h->url.path();
// qDebug() << "OSGBackgroundNode::realize - reading image file" << url.path();
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
osg::ref_ptr<osg::Image> image = osgDB::readImageFile(url.path().toStdString());
osg::ref_ptr<osg::Image> image = osgDB::readImageFile(url.path().toStdString());
texture->setImage(image.get());
osg::ref_ptr<osg::Drawable> quad = osg::createTexturedQuadGeometry(
@ -86,15 +76,15 @@ public:
self->setNode(camera);
}
OSGBackgroundNode *const self;
QUrl url;
};
/* class OSGBackgroundNode */
enum DirtyFlag { URL = 1 << 0 };
OSGBackgroundNode::OSGBackgroundNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
// qDebug() << "OSGBackgroundNode::OSGBackgroundNode";
qDebug() << "OSGBackgroundNode::OSGBackgroundNode";
}
OSGBackgroundNode::~OSGBackgroundNode()
@ -111,10 +101,28 @@ const QUrl OSGBackgroundNode::imageFile() const
void OSGBackgroundNode::setImageFile(const QUrl &url)
{
// qDebug() << "OSGBackgroundNode::setImageFile" << url;
if (h->acceptImageFile(url)) {
emit imageFileChanged(imageFile());
if (h->url != url) {
h->url = url;
setDirty(URL);
emit imageFileChanged(url);
}
}
void OSGBackgroundNode::update()
{
if (isDirty(URL)) {
h->updateNode();
}
}
void OSGBackgroundNode::attach(osgViewer::View *view)
{
update();
clearDirty();
}
void OSGBackgroundNode::detach(osgViewer::View *view)
{}
} // namespace osgQtQuick
#include "OSGBackgroundNode.moc"

View File

@ -53,6 +53,11 @@ signals:
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -55,7 +55,6 @@ 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),
@ -333,6 +332,7 @@ public:
osg::ref_ptr<osg::Camera> camera;
// Camera vertical field of view in degrees
qreal fieldOfView;
OSGNode *sceneNode;
@ -370,6 +370,8 @@ private slots:
/* 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";
@ -386,12 +388,11 @@ qreal OSGCamera::fieldOfView() const
return h->fieldOfView;
}
// Camera vertical field of view in degrees
void OSGCamera::setFieldOfView(qreal arg)
{
if (h->fieldOfView != arg) {
h->fieldOfView = arg;
setDirty(OSGCamera::FieldOfView);
setDirty(FieldOfView);
emit fieldOfViewChanged(fieldOfView());
}
}
@ -454,7 +455,6 @@ void OSGCamera::setClampToTerrain(bool arg)
{
if (h->clampToTerrain != arg) {
h->clampToTerrain = arg;
setDirty(OSGCamera::All);
emit clampToTerrainChanged(clampToTerrain());
}
}
@ -473,7 +473,7 @@ void OSGCamera::setAttitude(QVector3D arg)
{
if (h->attitude != arg) {
h->attitude = arg;
setDirty(OSGCamera::Attitude);
setDirty(Attitude);
emit attitudeChanged(attitude());
}
}
@ -487,7 +487,7 @@ void OSGCamera::setPosition(QVector3D arg)
{
if (h->position != arg) {
h->position = arg;
setDirty(OSGCamera::Position);
setDirty(Position);
emit positionChanged(position());
}
}
@ -507,26 +507,26 @@ void OSGCamera::setLogarithmicDepthBuffer(bool enabled)
void OSGCamera::update()
{
// h->updateAspectRatio();
if (isDirty(OSGCamera::FieldOfView)) {
if (isDirty(FieldOfView)) {
h->updateFieldOfView();
}
if (isDirty(OSGCamera::Position) || isDirty(OSGCamera::Attitude) || isDirty(OSGCamera::All)) {
if (isDirty(Position | Attitude)) {
h->updatePosition();
}
}
void OSGCamera::attach(osgViewer::View *view)
{
h->attachCamera(view->getCamera());
h->attachManipulator(view);
update();
clearDirty();
}
void OSGCamera::detach(osgViewer::View *view)
{
h->detachCamera(view->getCamera());
h->detachManipulator(view);
h->detachCamera(view->getCamera());
}
} // namespace osgQtQuick

View File

@ -75,8 +75,7 @@ class OSGQTQUICK_EXPORT OSGCamera : public OSGNode {
Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged)
Q_PROPERTY(bool logarithmicDepthBuffer READ logarithmicDepthBuffer WRITE setLogarithmicDepthBuffer NOTIFY logarithmicDepthBufferChanged)
enum DirtyFlag { Position, Attitude, FieldOfView, All };
friend class OSGViewport;
public:
explicit OSGCamera(QObject *parent = 0);
@ -115,9 +114,6 @@ public:
bool logarithmicDepthBuffer();
void setLogarithmicDepthBuffer(bool enabled);
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
signals:
void fieldOfViewChanged(qreal arg);
@ -140,7 +136,10 @@ private:
struct Hidden;
Hidden *h;
void update();
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -45,10 +45,11 @@ public:
void run()
{
load();
osg::Node *node = load();
emit loaded(url, node);
}
void load()
osg::Node *load()
{
QElapsedTimer t;
@ -57,8 +58,7 @@ public:
// qDebug() << "OSGFileLoader - load - currentContext" << QOpenGLContext::currentContext();
osg::Node *node = osgDB::readNodeFile(url.path().toStdString());
// qDebug() << "OSGFileLoader::load - reading node" << node << "took" << t.elapsed() << "ms";
emit loaded(url, node);
return node;
}
signals:
@ -75,33 +75,37 @@ private:
OSGFileNode * const self;
public:
Hidden(OSGFileNode *node) : QObject(node), self(node), url(), async(false), optimizeMode(OptimizeMode::None) {}
bool acceptSource(QUrl url)
{
// qDebug() << "OSGFileNode::acceptSource" << url;
if (this->url == url) {
return false;
}
this->url = url;
if (url.isValid()) {
realize();
} else {
qWarning() << "OSGFileNode::acceptNode - invalid url" << url;
self->setNode(NULL);
}
return true;
}
QUrl url;
QUrl source;
bool async;
OptimizeMode::Enum optimizeMode;
Hidden(OSGFileNode *node) : QObject(node), self(node), source(), async(false), optimizeMode(OptimizeMode::None) {}
void updateNode()
{
// qDebug() << "OSGFileNode::updateNode" << source;
if (!source.isValid()) {
self->setNode(NULL);
if (!source.isEmpty()) {
qWarning() << "OSGFileNode::updateNode - invalid source" << source;
}
}
if (false /*async*/) {
// not supported yet
// it is not clear if thread safety is insured...
asyncLoad(source);
} else {
setNode(syncLoad(source));
}
}
private:
osg::Node *syncLoad(const QUrl &url)
{
OSGFileLoader loader(url);
return loader.load();
}
void asyncLoad(const QUrl &url)
{
@ -112,64 +116,56 @@ private:
loader->start();
}
void syncLoad(const QUrl &url)
void setNode(osg::Node *node)
{
OSGFileLoader loader(url);
connect(&loader, &OSGFileLoader::loaded, this, &Hidden::onLoaded);
loader.load();
}
void realize()
{
qDebug() << "OSGFileNode::realize";
if (async) {
asyncLoad(url);
} else {
syncLoad(url);
}
}
bool acceptNode(osg::Node *node)
{
qDebug() << "OSGFileNode::acceptNode" << node;
qDebug() << "OSGFileNode::setNode" << node;
if (node && optimizeMode != OptimizeMode::None) {
// qDebug() << "OSGFileNode::acceptNode - optimize" << node << optimizeMode;
osgUtil::Optimizer optimizer;
optimizer.optimize(node, osgUtil::Optimizer::DEFAULT_OPTIMIZATIONS);
}
self->setNode(node);
return true;
}
private slots:
void onLoaded(const QUrl &url, osg::Node *node)
{
acceptNode(node);
// called in async mode
// question : is it thread safe to call setNode() ?
// could calling setDirty help? is setDirty() thread safe ?
setNode(node);
}
};
/* class OSGFileNode */
enum DirtyFlag { Source = 1 << 0, Async = 1 << 1, OptimizeMode = 1 << 2 };
OSGFileNode::OSGFileNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
qDebug() << "OSGFileNode::OSGFileNode";
setAsync(false);
setOptimizeMode(OptimizeMode::None);
}
OSGFileNode::~OSGFileNode()
{
qDebug() << "OSGFileNode::~OSGFileNode";
// qDebug() << "OSGFileNode::~OSGFileNode";
delete h;
}
const QUrl OSGFileNode::source() const
{
return h->url;
return h->source;
}
void OSGFileNode::setSource(const QUrl &url)
void OSGFileNode::setSource(const QUrl &source)
{
qDebug() << "OSGFileNode::setSource" << url;
if (h->acceptSource(url)) {
emit sourceChanged(source());
qDebug() << "OSGFileNode::setSource" << source;
if (h->source != source) {
h->source = source;
setDirty(Source);
emit sourceChanged(source);
}
}
@ -183,6 +179,7 @@ void OSGFileNode::setAsync(const bool async)
// qDebug() << "OSGFileNode::setAsync" << async;
if (h->async != async) {
h->async = async;
setDirty(Async);
emit asyncChanged(async);
}
}
@ -192,14 +189,37 @@ OptimizeMode::Enum OSGFileNode::optimizeMode() const
return h->optimizeMode;
}
void OSGFileNode::setOptimizeMode(OptimizeMode::Enum mode)
void OSGFileNode::setOptimizeMode(OptimizeMode::Enum optimizeMode)
{
// qDebug() << "OSGFileNode::setOptimizeMode" << mode;
if (h->optimizeMode != mode) {
h->optimizeMode = mode;
emit optimizeModeChanged(optimizeMode());
// qDebug() << "OSGFileNode::setOptimizeMode" << optimizeMode;
if (h->optimizeMode != optimizeMode) {
h->optimizeMode = optimizeMode;
setDirty(OptimizeMode);
emit optimizeModeChanged(optimizeMode);
}
}
void OSGFileNode::update()
{
if (isDirty(Async)) {
// do nothing...
}
if (isDirty(OptimizeMode)) {
// TODO: trigger a node update ?
}
if (isDirty(Source)) {
h->updateNode();
}
}
void OSGFileNode::attach(osgViewer::View *view)
{
update();
clearDirty();
}
void OSGFileNode::detach(osgViewer::View *view)
{}
} // namespace osgQtQuick
#include "OSGFileNode.moc"

View File

@ -50,7 +50,6 @@ class OSGQTQUICK_EXPORT OSGFileNode : public OSGNode {
Q_PROPERTY(osgQtQuick::OptimizeMode::Enum optimizeMode READ optimizeMode WRITE setOptimizeMode NOTIFY optimizeModeChanged)
public:
OSGFileNode(QObject *parent = 0);
virtual ~OSGFileNode();
@ -71,6 +70,11 @@ signals:
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -41,10 +41,28 @@ namespace osgQtQuick {
struct OSGGeoTransformNode::Hidden : public QObject {
Q_OBJECT
private:
OSGGeoTransformNode * const self;
osg::ref_ptr<osgEarth::GeoTransform> transform;
public:
OSGNode *childNode;
OSGNode *sceneNode;
float offset;
bool clampToTerrain;
bool intoTerrain;
QVector3D position;
Hidden(OSGGeoTransformNode *node) : QObject(node), self(node), childNode(NULL), sceneNode(NULL), offset(-1.0), clampToTerrain(false), intoTerrain(false)
{}
{
transform = new osgEarth::GeoTransform();
transform->setAutoRecomputeHeights(true);
self->setNode(transform);
}
bool acceptChildNode(OSGNode *node)
{
@ -86,36 +104,51 @@ public:
return true;
}
void updateNode()
void updateTransformNode()
{
// qDebug() << "OSGGeoTransformNode::updateNode" << this;
osgEarth::GeoTransform *transform = getOrCreateTransform();
bool updated = false;
if (transform->getNumChildren() == 0) {
if (childNode && childNode->node()) {
transform->addChild(childNode->node());
updated |= transform->addChild(childNode->node());
}
} else {
if (childNode && childNode->node()) {
if (transform->getChild(0) != childNode->node()) {
transform->removeChild(0, 1);
transform->addChild(childNode->node());
updated |= transform->removeChild(0, 1);
updated |= transform->addChild(childNode->node());
}
} else {
transform->removeChild(0, 1);
updated |= transform->removeChild(0, 1);
}
}
// if (updated) {
self->emitNodeChanged();
// }
}
osgEarth::MapNode *mapNode = NULL;
void updateSceneNode()
{
if (sceneNode && sceneNode->node()) {
mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
if (mapNode) {
transform->setTerrain(mapNode->getTerrain());
} else {
qWarning() << "OSGGeoTransformNode::updateNode - scene data does not contain a map node";
qWarning() << "OSGGeoTransformNode::updateScene - scene data does not contain a map node";
}
}
}
void updatePosition()
{
osgEarth::MapNode *mapNode = NULL;
if (sceneNode && sceneNode->node()) {
mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
}
if (!mapNode) {
qWarning() << "OSGGeoTransformNode::updatePosition - scene node does not contain a map node";
}
osgEarth::GeoPoint geoPoint;
if (mapNode) {
@ -139,49 +172,24 @@ public:
transform->setPosition(geoPoint);
}
osgEarth::GeoTransform *getOrCreateTransform()
{
if (transform.valid()) {
return transform.get();
}
transform = new osgEarth::GeoTransform();
transform->setAutoRecomputeHeights(true);
self->setNode(transform);
return transform.get();
}
OSGGeoTransformNode *const self;
osg::ref_ptr<osgEarth::GeoTransform> transform;
OSGNode *childNode;
OSGNode *sceneNode;
float offset;
bool clampToTerrain;
bool intoTerrain;
QVector3D position;
private slots:
void onChildNodeChanged(osg::Node *node)
{
qDebug() << "OSGGeoTransformNode::onChildNodeChanged" << node;
self->setDirty();
updateTransformNode();
}
void onSceneNodeChanged(osg::Node *node)
{
qDebug() << "OSGGeoTransformNode::onSceneNodeChanged" << node;
self->setDirty();
// TODO
}
};
/* class OSGGeoTransformNode */
enum DirtyFlag { Child = 1 << 0, Scene = 1 << 1, Position = 1 << 2, Clamp = 1 << 3 };
OSGGeoTransformNode::OSGGeoTransformNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
qDebug() << "OSGGeoTransformNode::OSGGeoTransformNode";
@ -189,31 +197,33 @@ OSGGeoTransformNode::OSGGeoTransformNode(QObject *parent) : OSGNode(parent), h(n
OSGGeoTransformNode::~OSGGeoTransformNode()
{
qDebug() << "OSGGeoTransformNode::~OSGGeoTransformNode";
// qDebug() << "OSGGeoTransformNode::~OSGGeoTransformNode";
delete h;
}
OSGNode *OSGGeoTransformNode::modelData()
OSGNode *OSGGeoTransformNode::childNode()
{
return h->childNode;
}
void OSGGeoTransformNode::setModelData(OSGNode *node)
void OSGGeoTransformNode::setChildNode(OSGNode *node)
{
if (h->acceptChildNode(node)) {
emit modelDataChanged(node);
setDirty(Child);
emit childNodeChanged(node);
}
}
OSGNode *OSGGeoTransformNode::sceneData()
OSGNode *OSGGeoTransformNode::sceneNode()
{
return h->sceneNode;
}
void OSGGeoTransformNode::setSceneData(OSGNode *node)
void OSGGeoTransformNode::setSceneNode(OSGNode *node)
{
if (h->acceptSceneNode(node)) {
emit sceneDataChanged(node);
setDirty(Scene);
emit sceneNodeChanged(node);
}
}
@ -226,7 +236,7 @@ void OSGGeoTransformNode::setClampToTerrain(bool arg)
{
if (h->clampToTerrain != arg) {
h->clampToTerrain = arg;
setDirty();
setDirty(Clamp);
emit clampToTerrainChanged(clampToTerrain());
}
}
@ -245,31 +255,36 @@ void OSGGeoTransformNode::setPosition(QVector3D arg)
{
if (h->position != arg) {
h->position = arg;
setDirty();
setDirty(Position);
emit positionChanged(position());
}
}
void OSGGeoTransformNode::update()
{
h->updateNode();
if (isDirty(Child)) {
h->updateTransformNode();
}
if (isDirty(Scene)) {
h->updateSceneNode();
}
if (isDirty(Clamp)) {}
if (isDirty(Position)) {
h->updatePosition();
}
}
void OSGGeoTransformNode::attach(osgViewer::View *view)
{
// qDebug() << "OSGGeoTransformNode::attach " << view;
if (h->childNode) {
h->childNode->attach(view);
}
OSGNode::attach(h->childNode, view);
update();
clearDirty();
}
void OSGGeoTransformNode::detach(osgViewer::View *view)
{
// qDebug() << "OSGGeoTransformNode::detach " << view;
if (h->childNode) {
h->childNode->detach(view);
}
OSGNode::detach(h->childNode, view);
}
} // namespace osgQtQuick

View File

@ -38,9 +38,9 @@ namespace osgQtQuick {
class OSGQTQUICK_EXPORT OSGGeoTransformNode : public OSGNode {
Q_OBJECT
// TODO rename to childNode
Q_PROPERTY(osgQtQuick::OSGNode *modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
Q_PROPERTY(osgQtQuick::OSGNode *modelData READ childNode WRITE setChildNode NOTIFY childNodeChanged)
// TODO rename to sceneNode
Q_PROPERTY(osgQtQuick::OSGNode * sceneData READ sceneData WRITE setSceneData NOTIFY sceneDataChanged)
Q_PROPERTY(osgQtQuick::OSGNode * sceneData READ sceneNode WRITE setSceneNode NOTIFY sceneNodeChanged)
Q_PROPERTY(bool clampToTerrain READ clampToTerrain WRITE setClampToTerrain NOTIFY clampToTerrainChanged)
Q_PROPERTY(bool intoTerrain READ intoTerrain NOTIFY intoTerrainChanged)
@ -51,11 +51,11 @@ public:
OSGGeoTransformNode(QObject *parent = 0);
virtual ~OSGGeoTransformNode();
OSGNode *modelData();
void setModelData(OSGNode *node);
OSGNode *childNode();
void setChildNode(OSGNode *node);
OSGNode *sceneData();
void setSceneData(OSGNode *node);
OSGNode *sceneNode();
void setSceneNode(OSGNode *node);
bool clampToTerrain() const;
void setClampToTerrain(bool arg);
@ -65,13 +65,10 @@ public:
QVector3D position() const;
void setPosition(QVector3D arg);
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
signals:
void modelDataChanged(OSGNode *node);
void childNodeChanged(OSGNode *node);
void sceneDataChanged(OSGNode *node);
void sceneNodeChanged(OSGNode *node);
void clampToTerrainChanged(bool arg);
void intoTerrainChanged(bool arg);
@ -83,6 +80,9 @@ private:
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -33,118 +33,160 @@
#include <QDebug>
namespace osgQtQuick {
enum DirtyFlag { Children = 1 << 0 };
struct OSGGroup::Hidden : public QObject {
Q_OBJECT
public:
Hidden(OSGGroup *node) : QObject(node), self(node), group(new osg::Group)
{}
private:
OSGGroup * self;
OSGGroup *self;
osg::ref_ptr<osg::Group> group;
QList<OSGNode *> children;
osg::ref_ptr<osg::Group> group;
QMap<OSGNode *, osg::Node *> cache;
static void append_child(QQmlListProperty<OSGNode> *list, OSGNode *child)
public:
Hidden(OSGGroup *node) : QObject(node), self(node), group(new osg::Group)
{
OSGGroup *group = qobject_cast<OSGGroup *>(list->object);
group = new osg::Group();
self->setNode(group);
}
if (group && child) {
group->h->cache[child] = child->node();
group->h->children.append(child);
if (child->node()) {
group->h->group->addChild(child->node());
emit group->nodeChanged(group->h->group);
}
QObject::connect(child, SIGNAL(nodeChanged(osg::Node *)), group->h, SLOT(onNodeChanged(osg::Node *)));
QList<OSGNode *> children;
void appendChild(OSGNode *childNode)
{
cache[childNode] = childNode->node();
children.append(childNode);
connect(childNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onChildNodeChanged(osg::Node *)), Qt::UniqueConnection);
self->setDirty(Children);
}
int countChild() const
{
return children.size();
}
OSGNode *atChild(int index) const
{
if (index >= 0 && index < children.size()) {
return children[index];
}
return 0;
}
void clearChild()
{
while (!children.isEmpty()) {
OSGNode *node = children.takeLast();
disconnect(node);
}
children.clear();
cache.clear();
self->setDirty(Children);
}
void updateGroupNode()
{
bool updated = false;
unsigned int index = 0;
QListIterator<OSGNode *> i(children);
while (i.hasNext()) {
OSGNode *childNode = i.next();
if (index < group->getNumChildren()) {
updated |= group->replaceChild(group->getChild(index), childNode->node());
} else {
updated |= group->addChild(childNode->node());
}
index++;
}
// removing eventual left overs
if (index < group->getNumChildren()) {
updated |= group->removeChild(index, group->getNumChildren() - index);
}
// if (updated) {
self->emitNodeChanged();
// }
}
/* QQmlListProperty<OSGNode> */
static void append_child(QQmlListProperty<OSGNode> *list, OSGNode *childNode)
{
Hidden *h = qobject_cast<Hidden *>(list->object);
h->appendChild(childNode);
}
static int count_child(QQmlListProperty<OSGNode> *list)
{
OSGGroup *group = qobject_cast<OSGGroup *>(list->object);
Hidden *h = qobject_cast<Hidden *>(list->object);
if (group) {
return group->h->children.size();
}
return 0;
return h->countChild();
}
static OSGNode *at_child(QQmlListProperty<OSGNode> *list, int index)
{
OSGGroup *group = qobject_cast<OSGGroup *>(list->object);
Hidden *h = qobject_cast<Hidden *>(list->object);
if (group && index >= 0 && index < group->h->children.size()) {
return group->h->children[index];
}
return 0;
return h->atChild(index);
}
static void clear_child(QQmlListProperty<OSGNode> *list)
{
OSGGroup *group = qobject_cast<OSGGroup *>(list->object);
Hidden *h = qobject_cast<Hidden *>(list->object);
if (group) {
while (!group->h->children.isEmpty()) {
OSGNode *node = group->h->children.takeLast();
if (node->parent() == group) {
node->deleteLater();
}
if (!node->parent()) {
node->deleteLater();
}
}
group->h->group->removeChild(0, group->h->group->getNumChildren());
group->h->cache.clear();
}
h->clearChild();
}
public slots:
void onNodeChanged(osg::Node *node)
private slots:
void onChildNodeChanged(osg::Node *node)
{
qDebug() << "OSGGroup::nodeChanged" << node;
qDebug() << "OSGGroup::onChildNodeChanged" << node;
OSGNode *obj = qobject_cast<OSGNode *>(sender());
if (obj) {
osg::Node *cacheNode = cache.value(obj, NULL);
if (cacheNode) {
group->removeChild(cacheNode);
}
if (node) {
group->addChild(node);
group->replaceChild(cacheNode, node);
} else {
// should not happen...
}
cache[obj] = node;
emit self->nodeChanged(group.get());
// emit self->nodeChanged(group.get());
}
}
};
OSGGroup::OSGGroup(QObject *parent) :
OSGNode(parent), h(new Hidden(this))
/* class OSGGGroupNode */
OSGGroup::OSGGroup(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
qDebug() << "OSGGroup::OSGGroup";
setNode(h->group.get());
}
OSGGroup::~OSGGroup()
{
qDebug() << "OSGGroup::~OSGGroup";
// qDebug() << "OSGGroup::~OSGGroup";
delete h;
}
QQmlListProperty<OSGNode> OSGGroup::children()
{
return QQmlListProperty<OSGNode>(this, 0,
return QQmlListProperty<OSGNode>(h, 0,
&Hidden::append_child,
&Hidden::count_child,
&Hidden::at_child,
&Hidden::clear_child);
}
void OSGGroup::update()
{
if (isDirty(Children)) {
h->updateGroupNode();
}
}
void OSGGroup::attach(osgViewer::View *view)
{
// qDebug() << "OSGGroup::attach " << view;
@ -152,8 +194,10 @@ void OSGGroup::attach(osgViewer::View *view)
while (i.hasNext()) {
OSGNode *node = i.next();
// qDebug() << "OSGGroup::attach - child" << node;
node->attach(view);
OSGNode::attach(node, view);
}
update();
clearDirty();
}
void OSGGroup::detach(osgViewer::View *view)
@ -163,7 +207,7 @@ void OSGGroup::detach(osgViewer::View *view)
while (i.hasNext()) {
OSGNode *node = i.next();
// qDebug() << "OSGGroup::detach - child" << node;
node->detach(view);
OSGNode::detach(node, view);
}
}
} // namespace osgQtQuick

View File

@ -45,12 +45,14 @@ public:
QQmlListProperty<OSGNode> children();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -46,21 +46,21 @@ private:
OSGNode::Hidden *const h;
};
struct OSGNode::Hidden /*: public QObject*/ {
// Q_OBJECT
struct OSGNode::Hidden : public QObject {
Q_OBJECT
friend class OSGNode;
public:
Hidden(OSGNode *node) : /*QObject(node),*/ self(node), dirty(0)
Hidden(OSGNode *node) : QObject(node), self(node), dirty(0)
{}
bool isDirty(int flag)
bool isDirty(int mask)
{
return (dirty && (1 << flag)) != 0;
return (dirty && mask) != 0;
}
void setDirty(int flag)
void setDirty(int mask)
{
// qDebug() << "OSGNode::setDirty BEGIN";
if (!dirty) {
@ -74,7 +74,7 @@ public:
node->setUpdateCallback(nodeUpdateCallback);
}
}
dirty |= 1 << flag;
dirty |= mask;
// qDebug() << "OSGNode::setDirty DONE";
}
@ -161,27 +161,48 @@ void OSGNode::setNode(osg::Node *node)
bool OSGNode::isDirty()
{
return h->isDirty(1);
return h->isDirty(0xFFFFFFFF);
}
bool OSGNode::isDirty(int flag)
bool OSGNode::isDirty(int mask)
{
return h->isDirty(flag);
return h->isDirty(mask);
}
void OSGNode::setDirty()
void OSGNode::setDirty(int mask)
{
h->setDirty(1);
h->setDirty(mask);
}
void OSGNode::setDirty(int flag)
void OSGNode::clearDirty()
{
h->setDirty(flag);
h->clearDirty();
}
void OSGNode::attach(OSGNode *node, osgViewer::View *view)
{
if (!node) {
return;
}
node->attach(view);
}
void OSGNode::detach(OSGNode *node, osgViewer::View *view)
{
if (!node) {
return;
}
node->detach(view);
}
void OSGNode::update()
{}
void OSGNode::attach(osgViewer::View *view)
{}
void OSGNode::detach(osgViewer::View *view)
{}
} // namespace osgQtQuick
#include "OSGNode.moc"

View File

@ -56,6 +56,7 @@ namespace osgQtQuick {
class OSGQTQUICK_EXPORT OSGNode : public QObject {
Q_OBJECT
friend class OSGViewport;
friend class NodeUpdateCallback;
public:
@ -65,14 +66,19 @@ public:
osg::Node *node() const;
void setNode(osg::Node *node);
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
protected:
bool isDirty();
bool isDirty(int flag);
void setDirty();
void setDirty(int flag);
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;
@ -81,7 +87,10 @@ private:
struct Hidden;
Hidden *h;
virtual void update() {};
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
virtual void update();
};
} // namespace osgQtQuick

View File

@ -40,13 +40,17 @@ namespace osgQtQuick {
struct OSGShapeNode::Hidden : public QObject {
Q_OBJECT
private:
OSGShapeNode * self;
public:
Hidden(OSGShapeNode *node) : QObject(node), self(node), shapeType(ShapeType::Sphere) {}
ShapeType::Enum shapeType;
void realize()
Hidden(OSGShapeNode *node) : QObject(node), self(node), shapeType(ShapeType::Sphere)
{}
void updateNode()
{
qDebug() << "OSGShapeNode::realize";
osg::Node *node = NULL;
switch (shapeType) {
@ -63,40 +67,26 @@ public:
node = ShapeUtils::create3DAxis();
break;
}
// Add the node to the scene:
// Add the node to the scene
self->setNode(node);
}
bool acceptShapeType(ShapeType::Enum type)
{
if (shapeType == type) {
return false;
}
qDebug() << "OSGShapeNode::acceptShapeType" << type;
shapeType = type;
realize();
return true;
}
OSGShapeNode *self;
ShapeType::Enum shapeType;
};
/* class OSGShapeNode */
enum DirtyFlag { Type = 1 << 0 };
// TODO turn into generic shape node...
// see http://trac.openscenegraph.org/projects/osg//wiki/Support/Tutorials/TransformsAndStates
OSGShapeNode::OSGShapeNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
qDebug() << "OSGShapeNode::OSGShapeNode";
h->realize();
setShapeType(ShapeType::Sphere);
}
OSGShapeNode::~OSGShapeNode()
{
qDebug() << "OSGShapeNode::~OSGShapeNode";
// qDebug() << "OSGShapeNode::~OSGShapeNode";
delete h;
}
@ -107,10 +97,28 @@ ShapeType::Enum OSGShapeNode::shapeType() const
void OSGShapeNode::setShapeType(ShapeType::Enum type)
{
if (h->acceptShapeType(type)) {
emit shapeTypeChanged(shapeType());
if (h->shapeType != type) {
h->shapeType = type;
setDirty(Type);
emit shapeTypeChanged(type);
}
}
void OSGShapeNode::update()
{
if (isDirty(Type)) {
h->updateNode();
}
}
void OSGShapeNode::attach(osgViewer::View *view)
{
update();
clearDirty();
}
void OSGShapeNode::detach(osgViewer::View *view)
{}
} // namespace osgQtQuick
#include "OSGShapeNode.moc"

View File

@ -55,6 +55,11 @@ signals:
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -42,8 +42,19 @@ namespace osgQtQuick {
struct OSGSkyNode::Hidden : public QObject {
Q_OBJECT
private:
OSGSkyNode * const self;
osg::ref_ptr<osgEarth::Util::SkyNode> skyNode;
public:
Hidden(OSGSkyNode *node) : QObject(node), self(node), sceneData(NULL), sunLightEnabled(true), minimumAmbientLight(0.03)
OSGNode *sceneNode;
bool sunLightEnabled;
QDateTime dateTime;
double minimumAmbientLight;
Hidden(OSGSkyNode *node) : QObject(node), self(node), sceneNode(NULL), sunLightEnabled(true), minimumAmbientLight(0.03)
{
dateTime = QDateTime::currentDateTime();
}
@ -54,59 +65,60 @@ public:
bool acceptSceneNode(OSGNode *node)
{
qDebug() << "OSGSkyNode::acceptSceneNode" << node;
if (sceneData == node) {
if (sceneNode == node) {
return false;
}
if (sceneData) {
disconnect(sceneData);
if (sceneNode) {
disconnect(sceneNode);
}
sceneData = node;
sceneNode = node;
if (sceneData) {
acceptNode(sceneData->node());
connect(sceneData, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onNodeChanged(osg::Node *)));
if (sceneNode) {
connect(sceneNode, SIGNAL(nodeChanged(osg::Node *)), this, SLOT(onSceneNodeChanged(osg::Node *)));
}
return true;
}
bool acceptNode(osg::Node *node)
void updateSkyNode()
{
qDebug() << "OSGSkyNode::acceptNode" << node;
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(node);
if (!sceneNode || !sceneNode->node()) {
qWarning() << "OSGSkyNode::acceptNode - scene node not valid";
self->setNode(NULL);
return;
}
osgEarth::MapNode *mapNode = osgEarth::MapNode::findMapNode(sceneNode->node());
if (!mapNode) {
qWarning() << "OSGSkyNode::acceptNode - scene data does not contain a map node";
return false;
qWarning() << "OSGSkyNode::acceptNode - scene node does not contain a map node";
self->setNode(NULL);
return;
}
if (!mapNode->getMap()->isGeocentric()) {
qWarning() << "OSGSkyNode::acceptNode - map node is not geocentric";
return false;
self->setNode(NULL);
return;
}
// create sky node
skyNode = createSimpleSky(mapNode);
// skyNode = createSilverLiningSky(mapNode);
if (!skyNode.valid()) {
skyNode = createSimpleSky(mapNode);
// skyNode = createSilverLiningSky(mapNode);
acceptSunLightEnabled(sunLightEnabled);
acceptDateTime(dateTime);
acceptMinimumAmbientLight(minimumAmbientLight);
// Ocean
// const osgEarth::Config & externals = mapNode->externalConfig();
// if (externals.hasChild("ocean")) {
// s_ocean = osgEarth::Util::OceanNode::create(osgEarth::Util::OceanOptions(externals.child("ocean")), mapNode);
// if (s_ocean) root->addChild(s_ocean);
// skyNode->setStarsVisible(false);
// Ocean
// const osgEarth::Config & externals = mapNode->externalConfig();
// if (externals.hasChild("ocean")) {
// s_ocean = osgEarth::Util::OceanNode::create(osgEarth::Util::OceanOptions(externals.child("ocean")), mapNode);
// if (s_ocean) root->addChild(s_ocean);
skyNode->addChild(node);
self->setNode(skyNode);
return true;
skyNode->addChild(sceneNode->node());
self->setNode(skyNode);
} else {
skyNode->removeChild(0, 1);
skyNode->addChild(sceneNode->node());
self->emitNodeChanged();
}
}
osgEarth::Util::SkyNode *createSimpleSky(osgEarth::MapNode *mapNode)
@ -130,65 +142,46 @@ public:
}
*/
bool acceptSunLightEnabled(bool enabled)
void updateSunLightEnabled()
{
// qDebug() << "OSGSkyNode::acceptSunLightEnabled" << enabled;
this->sunLightEnabled = enabled;
// TODO should be done in a node visitor...
if (skyNode) {
// skyNode->setLighting(sunLightEnabled ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
if (!skyNode.valid()) {
return;
}
return true;
// skyNode->setLighting(sunLightEnabled ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
}
bool acceptDateTime(QDateTime dateTime)
void updateDateTime()
{
qDebug() << "OSGSkyNode::acceptDateTime" << dateTime;
if (!skyNode.valid()) {
return;
}
if (!dateTime.isValid()) {
qWarning() << "OSGSkyNode::acceptDateTime - invalid date/time" << dateTime;
return false;
}
this->dateTime = dateTime;
// TODO should be done in a node visitor...
if (skyNode) {
QDate date = dateTime.date();
QTime time = dateTime.time();
double hours = time.hour() + (double)time.minute() / 60.0 + (double)time.second() / 3600.0;
skyNode->setDateTime(osgEarth::DateTime(date.year(), date.month(), date.day(), hours));
}
return true;
QDate date = dateTime.date();
QTime time = dateTime.time();
double hours = time.hour() + (double)time.minute() / 60.0 + (double)time.second() / 3600.0;
skyNode->setDateTime(osgEarth::DateTime(date.year(), date.month(), date.day(), hours));
}
bool acceptMinimumAmbientLight(double minimumAmbientLight)
void updateMinimumAmbientLight()
{
// qDebug() << "OSGSkyNode::acceptMinimumAmbientLight" << minimumAmbientLight;
this->minimumAmbientLight = minimumAmbientLight;
// TODO should be done in a node visitor...
if (skyNode) {
double d = minimumAmbientLight;
// skyNode->getSunLight()->setAmbient(osg::Vec4(d, d, d, 1.0f));
skyNode->setMinimumAmbient(osg::Vec4(d, d, d, 1.0f));
if (!skyNode.valid()) {
return;
}
return true;
double d = minimumAmbientLight;
// skyNode->getSunLight()->setAmbient(osg::Vec4(d, d, d, 1.0f));
skyNode->setMinimumAmbient(osg::Vec4(d, d, d, 1.0f));
}
void attachSkyNode(osgViewer::View *view)
{
if (!skyNode.valid()) {
qWarning() << "OSGSkyNode::attach - invalid sky node" << skyNode;
qWarning() << "OSGSkyNode::attachSkyNode - invalid sky node" << skyNode;
return;
}
skyNode->attach(view, 0);
skyNode->attach(view);
}
void detachSkyNode(osgViewer::View *view)
@ -196,44 +189,41 @@ public:
// TODO find a way to detach the skyNode (?)
}
OSGSkyNode *const self;
OSGNode *sceneData;
osg::ref_ptr<osgEarth::Util::SkyNode> skyNode;
bool sunLightEnabled;
QDateTime dateTime;
double minimumAmbientLight;
private slots:
void onNodeChanged(osg::Node *node)
void onSceneNodeChanged(osg::Node *node)
{
qDebug() << "OSGSkyNode::onNodeChanged" << node;
acceptNode(node);
qDebug() << "OSGSkyNode::onSceneNodeChanged" << node;
updateSkyNode();
}
};
/* class OSGSkyNode */
enum DirtyFlag { Child = 1 << 0, DateTime = 1 << 1, Light = 1 << 2 };
OSGSkyNode::OSGSkyNode(QObject *parent) : OSGNode(parent), h(new Hidden(this))
{
qDebug() << "OSGSkyNode::OSGSkyNode";
setSunLightEnabled(true);
setMinimumAmbientLight(0.03);
}
OSGSkyNode::~OSGSkyNode()
{
qDebug() << "OSGSkyNode::~OSGSkyNode";
// qDebug() << "OSGSkyNode::~OSGSkyNode";
delete h;
}
OSGNode *OSGSkyNode::sceneData()
OSGNode *OSGSkyNode::sceneNode()
{
return h->sceneData;
return h->sceneNode;
}
void OSGSkyNode::setSceneData(OSGNode *node)
void OSGSkyNode::setSceneNode(OSGNode *node)
{
if (h->acceptSceneNode(node)) {
emit sceneDataChanged(node);
setDirty(Child);
emit sceneNodeChanged(node);
}
}
@ -242,10 +232,12 @@ bool OSGSkyNode::sunLightEnabled()
return h->sunLightEnabled;
}
void OSGSkyNode::setSunLightEnabled(bool arg)
void OSGSkyNode::setSunLightEnabled(bool enabled)
{
if (h->acceptSunLightEnabled(arg)) {
emit sunLightEnabledChanged(sunLightEnabled());
if (h->sunLightEnabled != enabled) {
h->sunLightEnabled = enabled;
setDirty(Light);
emit sunLightEnabledChanged(enabled);
}
}
@ -254,10 +246,12 @@ QDateTime OSGSkyNode::dateTime()
return h->dateTime;
}
void OSGSkyNode::setDateTime(QDateTime arg)
void OSGSkyNode::setDateTime(QDateTime dateTime)
{
if (h->acceptDateTime(arg)) {
emit dateTimeChanged(dateTime());
if (h->dateTime != dateTime) {
h->dateTime = dateTime;
setDirty(DateTime);
emit dateTimeChanged(dateTime);
}
}
@ -266,29 +260,44 @@ double OSGSkyNode::minimumAmbientLight()
return h->minimumAmbientLight;
}
void OSGSkyNode::setMinimumAmbientLight(double arg)
void OSGSkyNode::setMinimumAmbientLight(double ambient)
{
if (h->acceptMinimumAmbientLight(arg)) {
emit minimumAmbientLightChanged(minimumAmbientLight());
if (h->minimumAmbientLight != ambient) {
h->minimumAmbientLight = ambient;
setDirty(Light);
emit minimumAmbientLightChanged(ambient);
}
}
void OSGSkyNode::update()
{
if (isDirty(Child)) {
h->updateSkyNode();
}
if (isDirty(Light)) {
h->updateSunLightEnabled();
h->updateMinimumAmbientLight();
}
if (isDirty(DateTime)) {
h->updateDateTime();
}
}
void OSGSkyNode::attach(osgViewer::View *view)
{
// qDebug() << "OSGSkyNode::attach " << view;
if (h->sceneData) {
h->sceneData->attach(view);
}
OSGNode::attach(h->sceneNode, view);
h->attachSkyNode(view);
update();
clearDirty();
}
void OSGSkyNode::detach(osgViewer::View *view)
{
// qDebug() << "OSGSkyNode::detach " << view;
h->detachSkyNode(view);
if (h->sceneData) {
h->sceneData->detach(view);
}
OSGNode::detach(h->sceneNode, view);
}
} // namespace osgQtQuick

View File

@ -44,7 +44,8 @@ QT_END_NAMESPACE
namespace osgQtQuick {
class OSGQTQUICK_EXPORT OSGSkyNode : public OSGNode {
Q_OBJECT Q_PROPERTY(osgQtQuick::OSGNode *sceneData READ sceneData WRITE setSceneData NOTIFY sceneDataChanged)
// TODO rename to sceneNode
Q_OBJECT Q_PROPERTY(osgQtQuick::OSGNode *sceneData READ sceneNode WRITE setSceneNode NOTIFY sceneNodeChanged)
Q_PROPERTY(bool sunLightEnabled READ sunLightEnabled WRITE setSunLightEnabled NOTIFY sunLightEnabledChanged)
Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY dateTimeChanged)
@ -54,8 +55,8 @@ public:
OSGSkyNode(QObject *parent = 0);
virtual ~OSGSkyNode();
OSGNode *sceneData();
void setSceneData(OSGNode *node);
OSGNode *sceneNode();
void setSceneNode(OSGNode *node);
bool sunLightEnabled();
void setSunLightEnabled(bool arg);
@ -66,11 +67,8 @@ public:
double minimumAmbientLight();
void setMinimumAmbientLight(double arg);
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
signals:
void sceneDataChanged(OSGNode *node);
void sceneNodeChanged(OSGNode *node);
void sunLightEnabledChanged(bool arg);
void dateTimeChanged(QDateTime arg);
@ -79,6 +77,11 @@ signals:
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -37,34 +37,61 @@
#include <QColor>
namespace osgQtQuick {
struct OSGTextNode::Hidden {
public:
struct OSGTextNode::Hidden : public QObject {
Q_OBJECT
private:
OSGTextNode * const self;
osg::ref_ptr<osgText::Text> text;
public:
QString textString;
QColor color;
Hidden(OSGTextNode *node) : QObject(node), self(node)
{
osg::ref_ptr<osgText::Font> textFont = createFont(QFont("Times"));
text = createText(osg::Vec3(-100, 20, 0), "Hello World", 20.0f,
textFont.get());
osg::ref_ptr<osg::Geode> textGeode = new osg::Geode();
textGeode->addDrawable(text.get());
#if 0
text->setAutoRotateToScreen(true);
self->setNode(textGeode.get());
#else
osg::Camera *camera = createHUDCamera(-100, 100, -100, 100);
camera->addChild(textGeode.get());
camera->getOrCreateStateSet()->setMode(
GL_LIGHTING, osg::StateAttribute::OFF);
self->setNode(camera);
#endif
}
void updateText()
{
text->setText(textString.toStdString(), osgText::String::ENCODING_UTF8);
}
void updateColor()
{
osg::Vec4 osgColor(
color.redF(),
color.greenF(),
color.blueF(),
color.alphaF());
text->setColor(osgColor);
}
};
OSGTextNode::OSGTextNode(QObject *node) : OSGNode(node), h(new Hidden)
{
osg::ref_ptr<osgText::Font> textFont = createFont(QFont("Times"));
/* class OSGTextNode */
h->text = createText(osg::Vec3(-100, 20, 0),
"The osgQtQuick :-)\n"
"И даже по русски!",
20.0f,
textFont.get());
osg::ref_ptr<osg::Geode> textGeode = new osg::Geode();
h->text->setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
textGeode->addDrawable(h->text.get());
#if 0
h->text->setAutoRotateToScreen(true);
setNode(textGeode.get());
#else
osg::Camera *camera = createHUDCamera(-100, 100, -100, 100);
camera->addChild(textGeode.get());
camera->getOrCreateStateSet()->setMode(
GL_LIGHTING, osg::StateAttribute::OFF);
setNode(camera);
#endif
}
enum DirtyFlag { Text = 1 << 0, Color = 1 << 1 };
OSGTextNode::OSGTextNode(QObject *node) : OSGNode(node), h(new Hidden(this))
{}
OSGTextNode::~OSGTextNode()
{
@ -73,42 +100,50 @@ OSGTextNode::~OSGTextNode()
QString OSGTextNode::text() const
{
return QString::fromUtf8(
h->text->getText().createUTF8EncodedString().data());
return h->textString;
}
void OSGTextNode::setText(const QString &text)
{
std::string oldText = h->text->getText().createUTF8EncodedString();
if (text.toStdString() != oldText) {
h->text->setText(text.toStdString(), osgText::String::ENCODING_UTF8);
if (h->textString != text) {
h->textString != text;
setDirty(Text);
emit textChanged(text);
}
}
QColor OSGTextNode::color() const
{
const osg::Vec4 osgColor = h->text->getColor();
return QColor::fromRgbF(
osgColor.r(),
osgColor.g(),
osgColor.b(),
osgColor.a());
return h->color;
}
void OSGTextNode::setColor(const QColor &color)
{
osg::Vec4 osgColor(
color.redF(),
color.greenF(),
color.blueF(),
color.alphaF());
if (h->text->getColor() != osgColor) {
h->text->setColor(osgColor);
if (h->color != color) {
h->color != color;
setDirty(Color);
emit colorChanged(color);
}
}
void OSGTextNode::update()
{
if (isDirty(Text)) {
h->updateText();
}
if (isDirty(Color)) {
h->updateColor();
}
}
void OSGTextNode::attach(osgViewer::View *view)
{
update();
clearDirty();
}
void OSGTextNode::detach(osgViewer::View *view)
{}
} // namespace osgQtQuick
#include "OSGTextNode.moc"

View File

@ -52,11 +52,14 @@ signals:
void textChanged(const QString &text);
void colorChanged(const QColor &color);
public slots:
private:
struct Hidden;
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -37,10 +37,23 @@ namespace osgQtQuick {
struct OSGTransformNode::Hidden : public QObject {
Q_OBJECT
private:
OSGTransformNode * const self;
osg::ref_ptr<osg::PositionAttitudeTransform> transform;
public:
OSGNode *childNode;
QVector3D scale;
QVector3D attitude;
QVector3D position;
Hidden(OSGTransformNode *node) : QObject(node), self(node), childNode(NULL)
{}
{
transform = new osg::PositionAttitudeTransform();
self->setNode(transform);
}
bool acceptChildNode(OSGNode *node)
{
@ -62,35 +75,40 @@ public:
return true;
}
void updateNode()
void updateTransformNode()
{
// qDebug() << "OSGTransformNode::updateNode" << this;
osg::PositionAttitudeTransform *transform = getOrCreateTransform();
bool updated = false;
if (transform->getNumChildren() == 0) {
if (childNode && childNode->node()) {
transform->addChild(childNode->node());
updated |= transform->addChild(childNode->node());
}
} else {
if (childNode && childNode->node()) {
if (transform->getChild(0) != childNode->node()) {
transform->removeChild(0, 1);
transform->addChild(childNode->node());
updated |= transform->removeChild(0, 1);
updated |= transform->addChild(childNode->node());
}
} else {
transform->removeChild(0, 1);
updated |= transform->removeChild(0, 1);
}
}
// if (updated) {
self->emitNodeChanged();
// }
}
// scale
void updateScale()
{
if ((scale.x() != 0.0) || (scale.y() != 0.0) || (scale.z() != 0.0)) {
transform->setScale(osg::Vec3d(scale.x(), scale.y(), scale.z()));
// transform->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
transform->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
}
}
// attitude
void updateAttitude()
{
double roll = osg::DegreesToRadians(attitude.x());
double pitch = osg::DegreesToRadians(attitude.y());
double yaw = osg::DegreesToRadians(attitude.z());
@ -98,45 +116,30 @@ public:
roll, osg::Vec3d(0, 1, 0),
pitch, osg::Vec3d(1, 0, 0),
yaw, osg::Vec3d(0, 0, -1));
transform->setAttitude(q);
// position
transform->setPosition(osg::Vec3d(position.x(), position.y(), position.z()));
}
osg::PositionAttitudeTransform *getOrCreateTransform()
void updatePosition()
{
if (transform.valid()) {
return transform.get();
}
transform = new osg::PositionAttitudeTransform();
self->setNode(transform);
return transform.get();
transform->setPosition(osg::Vec3d(position.x(), position.y(), position.z()));
}
OSGTransformNode *const self;
osg::ref_ptr<osg::PositionAttitudeTransform> transform;
OSGNode *childNode;
QVector3D scale;
QVector3D attitude;
QVector3D position;
private slots:
void onChildNodeChanged(osg::Node *node)
{
qDebug() << "OSGTransformNode::onChildNodeChanged" << node;
self->setDirty();
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";
@ -144,19 +147,20 @@ OSGTransformNode::OSGTransformNode(QObject *parent) : OSGNode(parent), h(new Hid
OSGTransformNode::~OSGTransformNode()
{
qDebug() << "OSGTransformNode::~OSGTransformNode";
// qDebug() << "OSGTransformNode::~OSGTransformNode";
delete h;
}
OSGNode *OSGTransformNode::modelData()
OSGNode *OSGTransformNode::childNode()
{
return h->childNode;
}
void OSGTransformNode::setModelData(OSGNode *node)
void OSGTransformNode::setChildNode(OSGNode *node)
{
if (h->acceptChildNode(node)) {
emit modelDataChanged(node);
setDirty(Child);
emit childNodeChanged(node);
}
}
@ -169,7 +173,7 @@ void OSGTransformNode::setScale(QVector3D arg)
{
if (h->scale != arg) {
h->scale = arg;
setDirty();
setDirty(Scale);
emit scaleChanged(scale());
}
}
@ -183,7 +187,7 @@ void OSGTransformNode::setAttitude(QVector3D arg)
{
if (h->attitude != arg) {
h->attitude = arg;
setDirty();
setDirty(Attitude);
emit attitudeChanged(attitude());
}
}
@ -197,31 +201,38 @@ void OSGTransformNode::setPosition(QVector3D arg)
{
if (h->position != arg) {
h->position = arg;
setDirty();
setDirty(Position);
emit positionChanged(position());
}
}
void OSGTransformNode::update()
{
h->updateNode();
if (isDirty(Child)) {
h->updateTransformNode();
}
if (isDirty(Scale)) {
h->updateScale();
}
if (isDirty(Attitude)) {
h->updateAttitude();
}
if (isDirty(Position)) {
h->updatePosition();
}
}
void OSGTransformNode::attach(osgViewer::View *view)
{
// qDebug() << "OSGTransformNode::attach " << view;
if (h->childNode) {
h->childNode->attach(view);
}
OSGNode::attach(h->childNode, view);
update();
clearDirty();
}
void OSGTransformNode::detach(osgViewer::View *view)
{
// qDebug() << "OSGTransformNode::detach " << view;
if (h->childNode) {
h->childNode->detach(view);
}
OSGNode::detach(h->childNode, view);
}
} // namespace osgQtQuick

View File

@ -38,7 +38,7 @@ namespace osgQtQuick {
class OSGQTQUICK_EXPORT OSGTransformNode : public OSGNode {
Q_OBJECT
// TODO rename to childNode
Q_PROPERTY(osgQtQuick::OSGNode *modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
Q_PROPERTY(osgQtQuick::OSGNode *modelData READ childNode WRITE setChildNode NOTIFY childNodeChanged)
Q_PROPERTY(QVector3D scale READ scale WRITE setScale NOTIFY scaleChanged)
Q_PROPERTY(QVector3D attitude READ attitude WRITE setAttitude NOTIFY attitudeChanged)
@ -48,8 +48,8 @@ public:
OSGTransformNode(QObject *parent = 0);
virtual ~OSGTransformNode();
OSGNode *modelData();
void setModelData(OSGNode *node);
OSGNode *childNode();
void setChildNode(OSGNode *node);
QVector3D scale() const;
void setScale(QVector3D arg);
@ -60,11 +60,8 @@ public:
QVector3D position() const;
void setPosition(QVector3D arg);
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
signals:
void modelDataChanged(OSGNode *node);
void childNodeChanged(OSGNode *node);
void scaleChanged(QVector3D arg);
void attitudeChanged(QVector3D arg);
@ -75,6 +72,9 @@ private:
Hidden *h;
virtual void update();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
};
} // namespace osgQtQuick

View File

@ -72,11 +72,8 @@ public:
OSGCamera *camera();
void setCamera(OSGCamera *camera);
virtual Renderer *createRenderer() const;
virtual void releaseResources();
virtual void attach(osgViewer::View *view);
virtual void detach(osgViewer::View *view);
Renderer *createRenderer() const;
void releaseResources();
signals:
void updateModeChanged(UpdateMode::Enum mode);
@ -97,6 +94,9 @@ protected:
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
void attach(osgViewer::View *view);
void detach(osgViewer::View *view);
private:
struct Hidden;
Hidden *h;