summaryrefslogtreecommitdiffstats
path: root/src/uscxml/plugins/invoker/graphics
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2012-12-27 21:17:45 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2012-12-27 21:17:45 (GMT)
commit7b8da7c5b88714f8b4892c83703c16b19a6cb80d (patch)
tree9f78c6399274a937c662454d51ab4314ad9ec903 /src/uscxml/plugins/invoker/graphics
parentfa05389f050004a14787cd7b4ebb6e0b54e0e4af (diff)
downloaduscxml-7b8da7c5b88714f8b4892c83703c16b19a6cb80d.zip
uscxml-7b8da7c5b88714f8b4892c83703c16b19a6cb80d.tar.gz
uscxml-7b8da7c5b88714f8b4892c83703c16b19a6cb80d.tar.bz2
New scenegraph invoker using OpenSceneGraph
Ultimately, the scenegraph invoker ought to use x3d
Diffstat (limited to 'src/uscxml/plugins/invoker/graphics')
-rw-r--r--src/uscxml/plugins/invoker/graphics/openscenegraph/CompositeDisplay.cpp117
-rw-r--r--src/uscxml/plugins/invoker/graphics/openscenegraph/CompositeDisplay.h46
-rw-r--r--src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp291
-rw-r--r--src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h48
4 files changed, 500 insertions, 2 deletions
diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/CompositeDisplay.cpp b/src/uscxml/plugins/invoker/graphics/openscenegraph/CompositeDisplay.cpp
new file mode 100644
index 0000000..c9b00b6
--- /dev/null
+++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/CompositeDisplay.cpp
@@ -0,0 +1,117 @@
+#include "CompositeDisplay.h"
+
+CompositeDisplay::CompositeDisplay(unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height,
+ int screenId)
+{
+ _waitForViewOp = false;
+ unsigned int tWidth = 0;
+ unsigned int tHeight = 0;
+ getResolution(tWidth, tHeight, screenId);
+
+ osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
+ traits->doubleBuffer = true;
+ traits->sharedContext = 0;
+ traits->screenNum = screenId;
+
+ if (width == 0 || height == 0 || (width == tWidth && height == tHeight)) {
+ // fullscreen
+ traits->windowDecoration = false;
+ traits->width = tWidth;
+ traits->height = tHeight;
+ traits->x = 0;
+ traits->y = 0;
+ } else {
+ // Start with given resolution
+ traits->windowDecoration = true;
+ traits->x = x;
+ traits->y = y;
+ traits->width = width;
+ traits->height = height;
+ }
+
+ _gc = osg::GraphicsContext::createGraphicsContext(traits.get());
+ if (_gc.valid()) {
+ _gc->setClearColor(osg::Vec4f(1.0f,1.0f,1.0f,1.0f));
+ _gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+
+ _width = traits->width;
+ _height = traits->height;
+
+ setRunMaxFrameRate(30);
+// setRunFrameScheme(osgViewer::ViewerBase::ON_DEMAND);
+ setThreadingModel(osgViewer::Viewer::AutomaticSelection);
+}
+
+CompositeDisplay::~CompositeDisplay() {}
+
+void CompositeDisplay::frame(double simulationTime) {
+ tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
+ CompositeViewer::frame();
+}
+
+bool CompositeDisplay::checkNeedToDoFrame() {
+ return CompositeViewer::checkNeedToDoFrame();
+}
+
+void CompositeDisplay::addView(const std::string& name, osg::Viewport* v, osgViewer::View* view) {
+ tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
+ _viewports[name] = v;
+
+ _views[name] = view;
+ _views[name]->setName(name);
+ _views[name]->getCamera()->setName(name);
+ _views[name]->setCameraManipulator(new osgGA::TrackballManipulator);
+
+ // add the state manipulator
+ osg::ref_ptr<osgGA::StateSetManipulator> statesetManipulator = new osgGA::StateSetManipulator;
+ statesetManipulator->setStateSet(_views[name]->getCamera()->getOrCreateStateSet());
+ _views[name]->addEventHandler( statesetManipulator.get() );
+
+ _views[name]->addEventHandler( new osgViewer::StatsHandler );
+ _views[name]->addEventHandler( new osgViewer::HelpHandler );
+ _views[name]->addEventHandler( new osgViewer::WindowSizeHandler );
+ _views[name]->addEventHandler( new osgViewer::ThreadingHandler );
+
+ _views[name]->getCamera()->setViewport(v);
+
+ // set graphic context
+ _views[name]->getCamera()->setGraphicsContext(_gc.get());
+ CompositeViewer::addView(_views[name]);
+
+}
+
+void CompositeDisplay::moveView(const std::string& name, osg::Viewport* v) {
+ tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
+ const osg::GraphicsContext::Traits* traits = _gc->getTraits();
+ osg::Viewport* absoluteVp = new osg::Viewport(v->x() * (traits->width/100.0),
+ v->y() * (traits->height/100.0),
+ v->width() * (traits->width/100.0),
+ v->height() * (traits->height/100.0));
+ _views[name]->getCamera()->setViewport(absoluteVp);
+}
+
+void CompositeDisplay::removeView(const std::string& name) {
+ tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
+
+ _views[name]->getCamera()->setGraphicsContext(NULL);
+ _views[name]->getCamera()->setViewport(NULL);
+
+ CompositeViewer::removeView(_views[name]);
+
+ if (_views.find(name) != _views.end()) {
+ _views.erase(name);
+ }
+ if (_viewports.find(name) != _viewports.end())
+ _viewports.erase(name);
+}
+
+osg::GraphicsContext::WindowingSystemInterface* CompositeDisplay::wsi = NULL;
+void CompositeDisplay::getResolution(unsigned int& width, unsigned int& height, int screenId) {
+ if (!wsi)
+ wsi = osg::GraphicsContext::getWindowingSystemInterface();
+ wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(screenId), width, height);
+}
diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/CompositeDisplay.h b/src/uscxml/plugins/invoker/graphics/openscenegraph/CompositeDisplay.h
new file mode 100644
index 0000000..51e17c1
--- /dev/null
+++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/CompositeDisplay.h
@@ -0,0 +1,46 @@
+#ifndef COMPOSITEDISPLAY_H_W2MX9CXP
+#define COMPOSITEDISPLAY_H_W2MX9CXP
+
+#include "uscxml/concurrency/tinythread.h"
+#include <osgGA/TrackballManipulator>
+#include <osgViewer/CompositeViewer>
+#include <osgViewer/ViewerEventHandlers>
+#include <osgGA/StateSetManipulator>
+#include <assert.h>
+#include <iostream>
+
+class CompositeDisplay : public osgViewer::CompositeViewer {
+public:
+ CompositeDisplay(unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height,
+ int screenId);
+ virtual ~CompositeDisplay();
+
+ virtual void addView(const std::string& name, osg::Viewport* v, osgViewer::View* view);
+ virtual void moveView(const std::string& name, osg::Viewport* v);
+ virtual void removeView(const std::string& name);
+
+ virtual void frame(double simulationTime);
+ virtual bool checkNeedToDoFrame();
+
+ int getWidth() { return _width; }
+ int getHeight() { return _height; }
+
+ static void getResolution(unsigned int& width, unsigned int& height, int screenId);
+
+protected:
+ tthread::recursive_mutex _mutex;
+ tthread::condition_variable _monitor;
+ bool _waitForViewOp;
+ std::map<std::string, osgViewer::View*> _views;
+ std::map<std::string, osg::Viewport*> _viewports;
+ osg::ref_ptr<osg::GraphicsContext> _gc;
+
+ static osg::GraphicsContext::WindowingSystemInterface* wsi;
+ int _width, _height;
+};
+
+
+#endif /* end of include guard: COMPOSITEDISPLAY_H_W2MX9CXP */
diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp
index 33aba1d..5c3dfef 100644
--- a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp
+++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp
@@ -1,4 +1,5 @@
#include "OSGInvoker.h"
+#include "uscxml/URL.h"
#include <glog/logging.h>
#ifdef BUILD_AS_PLUGINS
@@ -6,7 +7,7 @@
#endif
namespace uscxml {
-
+
#ifdef BUILD_AS_PLUGINS
PLUMA_CONNECTOR
bool connect(pluma::Host& host) {
@@ -14,7 +15,7 @@ bool connect(pluma::Host& host) {
return true;
}
#endif
-
+
OSGInvoker::OSGInvoker() {
}
@@ -42,6 +43,292 @@ void OSGInvoker::sendToParent(SendRequest& req) {
}
void OSGInvoker::invoke(InvokeRequest& req) {
+ tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
+
+ Arabica::XPath::NodeSet<std::string> content = Interpreter::filterChildElements("content", req.dom);
+
+ std::set<std::string> validChilds;
+ validChilds.insert("display");
+ processChildren(validChilds, content[0]);
+}
+
+void OSGInvoker::runOnMainThread() {
+ _displays_t::iterator dispIter = _displays.begin();
+ if (_mutex.try_lock()) {
+ while(dispIter != _displays.end()) {
+ dispIter->second->osgViewer::ViewerBase::frame();
+ dispIter++;
+ }
+ _mutex.unlock();
+ }
+}
+
+void OSGInvoker::processDisplay(const Arabica::DOM::Node<std::string>& element) {
+// std::cout << element << std::endl;
+
+ if (_displays.find(element) == _displays.end()) {
+
+ int screenId = 0;
+ unsigned int actualX = 0;
+ unsigned int actualY = 0;
+ unsigned int actualWidth = 0;
+ unsigned int actualHeight = 0;
+ getViewport(element, actualX, actualY, actualWidth, actualHeight, screenId);
+
+ CompositeDisplay* compDisp = new CompositeDisplay(actualX, actualY, actualWidth, actualHeight, screenId);
+ _displays[element] = compDisp;
+
+ std::set<std::string> validChilds;
+ validChilds.insert("viewport");
+ processChildren(validChilds, element);
+ }
+}
+
+void OSGInvoker::processViewport(const Arabica::DOM::Node<std::string>& element) {
+ if (_displays.find(element.getParentNode()) == _displays.end())
+ return;
+
+ CompositeDisplay* compDisp = _displays[element.getParentNode()];
+ osgViewer::View* sceneView = new osgViewer::View();
+ _views[element] = sceneView;
+
+ osg::Group* group = new osg::Group();
+ _nodes[element] = group;
+ sceneView->setSceneData(group);
+
+ std::string name = (HAS_ATTR(element, "id") ? ATTR(element, "id") : Interpreter::getUUID());
+
+ unsigned int actualX = 0;
+ unsigned int actualY = 0;
+ unsigned int actualWidth = 0;
+ unsigned int actualHeight = 0;
+ getViewport(element, actualX, actualY, actualWidth, actualHeight, compDisp);
+
+ osg::Viewport* viewPort = new osg::Viewport(actualX, actualY, actualWidth, actualHeight);
+ compDisp->addView(name, viewPort, sceneView);
+
+ std::set<std::string> validChilds;
+ validChilds.insert("translation");
+ validChilds.insert("rotation");
+ validChilds.insert("scale");
+ validChilds.insert("node");
+ processChildren(validChilds, element);
+}
+
+void OSGInvoker::processTranslation(const Arabica::DOM::Node<std::string>& element) {
+ assert(_nodes.find(element.getParentNode()) != _nodes.end());
+ osg::Node* node = _nodes[element.getParentNode()];
+
+ double x = 0, y = 0, z = 0;
+ if (HAS_ATTR(element, "x"))
+ x = strTo<float>(ATTR(element, "x"));
+ if (HAS_ATTR(element, "y"))
+ y = strTo<float>(ATTR(element, "y"));
+ if (HAS_ATTR(element, "z"))
+ z = strTo<float>(ATTR(element, "z"));
+
+ osg::Matrix translate;
+ translate.makeTranslate(x, y, z);
+
+ osg::MatrixTransform* transform = new osg::MatrixTransform();
+ transform->setMatrix(translate);
+ node->asGroup()->addChild(transform);
+ _nodes[element] = transform;
+
+ std::set<std::string> validChilds;
+ validChilds.insert("translation");
+ validChilds.insert("rotation");
+ validChilds.insert("scale");
+ validChilds.insert("node");
+ processChildren(validChilds, element);
+}
+
+void OSGInvoker::processRotation(const Arabica::DOM::Node<std::string>& element) {
+ assert(_nodes.find(element.getParentNode()) != _nodes.end());
+ osg::Node* node = _nodes[element.getParentNode()];
+
+ double x = 0, y = 0, z = 0, angle = 0;
+ if (HAS_ATTR(element, "x"))
+ x = strTo<float>(ATTR(element, "x"));
+ if (HAS_ATTR(element, "y"))
+ y = strTo<float>(ATTR(element, "y"));
+ if (HAS_ATTR(element, "z"))
+ z = strTo<float>(ATTR(element, "z"));
+ if (HAS_ATTR(element, "angle"))
+ z = strTo<float>(ATTR(element, "angle"));
+
+ osg::Matrix rotation;
+ rotation.makeRotate(angle, x, y, z);
+
+ osg::MatrixTransform* transform = new osg::MatrixTransform();
+ transform->setMatrix(rotation);
+ node->asGroup()->addChild(transform);
+ _nodes[element] = transform;
+
+ std::set<std::string> validChilds;
+ validChilds.insert("translation");
+ validChilds.insert("rotation");
+ validChilds.insert("scale");
+ validChilds.insert("node");
+ processChildren(validChilds, element);
+}
+
+void OSGInvoker::processScale(const Arabica::DOM::Node<std::string>& element) {
+ assert(_nodes.find(element.getParentNode()) != _nodes.end());
+ osg::Node* node = _nodes[element.getParentNode()];
+
+ double x = 1, y = 1, z = 1;
+ if (HAS_ATTR(element, "x"))
+ x = strTo<float>(ATTR(element, "x"));
+ if (HAS_ATTR(element, "y"))
+ y = strTo<float>(ATTR(element, "y"));
+ if (HAS_ATTR(element, "z"))
+ z = strTo<float>(ATTR(element, "z"));
+
+ osg::Matrix scale;
+ scale.makeScale(x, y, z);
+
+ osg::MatrixTransform* transform = new osg::MatrixTransform();
+ transform->setMatrix(scale);
+ node->asGroup()->addChild(transform);
+ _nodes[element] = transform;
+
+ std::set<std::string> validChilds;
+ validChilds.insert("translation");
+ validChilds.insert("rotation");
+ validChilds.insert("scale");
+ validChilds.insert("node");
+ processChildren(validChilds, element);
+}
+
+void OSGInvoker::processNode(const Arabica::DOM::Node<std::string>& element) {
+ assert(_nodes.find(element.getParentNode()) != _nodes.end());
+ osg::Node* parent = _nodes[element.getParentNode()];
+
+ std::string filename;
+ if (HAS_ATTR(element, "src")) {
+ filename = ATTR(element, "src");
+
+ if (filename.length() > 0) {
+ std::string extension;
+ size_t extensionStart = filename.find_last_of(".");
+ if (extensionStart != std::string::npos) {
+ extension = filename.substr(extensionStart);
+ }
+
+ URL srcURI(filename);
+ if (!srcURI.toAbsolute(_interpreter->getBaseURI())) {
+ LOG(ERROR) << "invoke element has relative src URI with no baseURI set.";
+ return;
+ }
+ filename = srcURI.asLocalFile(extension);
+ osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(filename);
+ if (model.get())
+ parent->asGroup()->addChild(model);
+
+ }
+ }
+}
+
+void OSGInvoker::processChildren(const std::set<std::string>& validChildren, const Arabica::DOM::Node<std::string>& element) {
+ Arabica::DOM::NodeList<std::string> childs = element.getChildNodes();
+ for (int i = 0; i < childs.getLength(); ++i) {
+ if (childs.item(i).getNodeType() != Arabica::DOM::Node_base::ELEMENT_NODE)
+ continue;
+ if (false) {
+ } else if (boost::iequals(LOCALNAME(childs.item(i)), "node") &&
+ validChildren.find("node") != validChildren.end()) {
+ processNode(childs.item(i));
+ } else if (boost::iequals(LOCALNAME(childs.item(i)), "translation") &&
+ validChildren.find("translation") != validChildren.end()) {
+ processTranslation(childs.item(i));
+ } else if (boost::iequals(LOCALNAME(childs.item(i)), "rotation") &&
+ validChildren.find("rotation") != validChildren.end()) {
+ processRotation(childs.item(i));
+ } else if (boost::iequals(LOCALNAME(childs.item(i)), "scale") &&
+ validChildren.find("scale") != validChildren.end()) {
+ processScale(childs.item(i));
+ } else if (boost::iequals(LOCALNAME(childs.item(i)), "viewport") &&
+ validChildren.find("viewport") != validChildren.end()) {
+ processViewport(childs.item(i));
+ } else if (boost::iequals(LOCALNAME(childs.item(i)), "display") &&
+ validChildren.find("display") != validChildren.end()) {
+ processDisplay(childs.item(i));
+ } else {
+ LOG(INFO) << "Unknown XML element " << TAGNAME(childs.item(i));
+ }
+ }
+}
+
+void OSGInvoker::getViewport(const Arabica::DOM::Node<std::string>& element,
+ unsigned int& x,
+ unsigned int& y,
+ unsigned int& width,
+ unsigned int& height,
+ CompositeDisplay* display) {
+ getViewport(element, x, y, width, height, display->getWidth(), display->getHeight());
+
+}
+
+void OSGInvoker::getViewport(const Arabica::DOM::Node<std::string>& element,
+ unsigned int& x,
+ unsigned int& y,
+ unsigned int& width,
+ unsigned int& height,
+ int& screenId)
+{
+
+ screenId = (HAS_ATTR(element, "screenId") ? strTo<int>(ATTR(element, "screenId")) : 0);
+
+ unsigned int fullWidth = 0;
+ unsigned int fullHeight = 0;
+ CompositeDisplay::getResolution(fullWidth, fullHeight, screenId);
+ getViewport(element, x, y, width, height, fullWidth, fullHeight);
+}
+
+void OSGInvoker::getViewport(const Arabica::DOM::Node<std::string>& element,
+ unsigned int& x,
+ unsigned int& y,
+ unsigned int& width,
+ unsigned int& height,
+ unsigned int fullWidth,
+ unsigned int fullHeight)
+{
+ if (HAS_ATTR(element, "x")) {
+ NumAttr xAttr = NumAttr(ATTR(element, "x"));
+ x = strTo<float>(xAttr.value);
+ if (boost::iequals(xAttr.unit, "%"))
+ x = (x * fullWidth) / 100;
+ }
+ if (HAS_ATTR(element, "y")) {
+ NumAttr yAttr = NumAttr(ATTR(element, "y"));
+ y = strTo<float>(yAttr.value);
+ if (boost::iequals(yAttr.unit, "%"))
+ y = (y * fullHeight) / 100;
+ }
+ if (HAS_ATTR(element, "width")) {
+ NumAttr widthAttr = NumAttr(ATTR(element, "width"));
+ width = strTo<float>(widthAttr.value);
+ if (boost::iequals(widthAttr.unit, "%"))
+ width = (width * fullWidth) / 100;
+ }
+ if (HAS_ATTR(element, "height")) {
+ NumAttr heightAttr = NumAttr(ATTR(element, "height"));
+ height = strTo<float>(heightAttr.value);
+ if (boost::iequals(heightAttr.unit, "%"))
+ height = (height * fullHeight) / 100;
+ }
+}
+
+osgViewer::View* OSGInvoker::getView(const Arabica::DOM::Node<std::string>& element) {
+ Arabica::DOM::Node<std::string> curr = element;
+ while(curr && !boost::iequals(LOCALNAME(curr), "viewport")) {
+ curr = curr.getParentNode();
+ }
+ if (curr && _views.find(curr) != _views.end())
+ return _views[curr];
+ return NULL;
}
+
} \ No newline at end of file
diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h
index ed95a78..cf1556e 100644
--- a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h
+++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.h
@@ -2,6 +2,10 @@
#define OSGINVOKER_H_H6T4R8HU
#include <uscxml/Interpreter.h>
+#include "CompositeDisplay.h"
+#include <osg/MatrixTransform>
+#include <osgDB/ReadFile>
+#include <set>
#ifdef BUILD_AS_PLUGINS
#include "uscxml/plugins/Plugins.h"
@@ -29,7 +33,51 @@ public:
virtual void invoke(InvokeRequest& req);
virtual void sendToParent(SendRequest& req);
+ virtual void runOnMainThread();
+
protected:
+ void processDisplay(const Arabica::DOM::Node<std::string>& element);
+ void processViewport(const Arabica::DOM::Node<std::string>& element);
+ void processTranslation(const Arabica::DOM::Node<std::string>& element);
+ void processRotation(const Arabica::DOM::Node<std::string>& element);
+ void processScale(const Arabica::DOM::Node<std::string>& element);
+ void processNode(const Arabica::DOM::Node<std::string>& element);
+ void processChildren(const std::set<std::string>& validChildren, const Arabica::DOM::Node<std::string>& element);
+
+ void getViewport(const Arabica::DOM::Node<std::string>& element,
+ unsigned int& x,
+ unsigned int& y,
+ unsigned int& width,
+ unsigned int& height,
+ int& screenId);
+
+ void getViewport(const Arabica::DOM::Node<std::string>& element,
+ unsigned int& x,
+ unsigned int& y,
+ unsigned int& width,
+ unsigned int& height,
+ CompositeDisplay* display);
+
+ void getViewport(const Arabica::DOM::Node<std::string>& element,
+ unsigned int& x,
+ unsigned int& y,
+ unsigned int& width,
+ unsigned int& height,
+ unsigned int fullWidth,
+ unsigned int fullHeight);
+
+ osgViewer::View* getView(const Arabica::DOM::Node<std::string>& element);
+
+ std::map<Arabica::DOM::Node<std::string>, CompositeDisplay*> _displays;
+ typedef std::map<Arabica::DOM::Node<std::string>, CompositeDisplay*> _displays_t;
+
+ std::map<Arabica::DOM::Node<std::string>, osgViewer::View*> _views;
+ typedef std::map<Arabica::DOM::Node<std::string>, osgViewer::View*> _views_t;
+
+ std::map<Arabica::DOM::Node<std::string>, osg::Node*> _nodes;
+ typedef std::map<Arabica::DOM::Node<std::string>, osg::Node*> _nodes_t;
+
+ tthread::recursive_mutex _mutex;
std::string _invokeId;
};