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:
parent
7c21a09b7f
commit
6c82a7f01a
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user