summaryrefslogtreecommitdiffstats
path: root/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp')
-rw-r--r--src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp291
1 files changed, 289 insertions, 2 deletions
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