diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2012-12-27 21:17:45 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2012-12-27 21:17:45 (GMT) |
commit | 7b8da7c5b88714f8b4892c83703c16b19a6cb80d (patch) | |
tree | 9f78c6399274a937c662454d51ab4314ad9ec903 /src/uscxml/plugins | |
parent | fa05389f050004a14787cd7b4ebb6e0b54e0e4af (diff) | |
download | uscxml-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')
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; }; |