/* OpenSceneGraph example, osgcubemap. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // class to handle events with a pick class PickHandler : public osgGA::GUIEventHandler { public: PickHandler(osgGA::Device* device): _device(device) {} ~PickHandler() {} bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa); virtual void pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea); void setLabel(const std::string& name, float x, float y) { osg::ref_ptr ea = new osgGA::GUIEventAdapter(); ea->setEventType(osgGA::GUIEventAdapter::USER); ea->setName("pick-result"); ea->setUserValue("name", name); ea->setUserValue("x", x); ea->setUserValue("y", y); _device->sendEvent(*ea); } protected: osg::ref_ptr _device; }; bool PickHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa) { switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::PUSH): { osgViewer::View* view = dynamic_cast(&aa); if (view) pick(view,ea); return false; } case(osgGA::GUIEventAdapter::KEYUP): { if (ea.getKey() == 't') { osg::ref_ptr user_event = new osgGA::GUIEventAdapter(); user_event->setEventType(osgGA::GUIEventAdapter::USER); user_event->setUserValue("vec2f", osg::Vec2f(1.0f,2.0f)); user_event->setUserValue("vec3f", osg::Vec3f(1.0f,2.0f, 3.0f)); user_event->setUserValue("vec4f", osg::Vec4f(1.0f,2.0f, 3.0f, 4.0f)); user_event->setUserValue("vec2d", osg::Vec2d(1.0,2.0)); user_event->setUserValue("vec3d", osg::Vec3d(1.0,2.0, 3.0)); user_event->setUserValue("vec4d", osg::Vec4d(1.0,2.0, 3.0, 4.0)); user_event->setName("osc_test_1"); _device->sendEvent(*user_event); } } default: return false; } } void PickHandler::pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea) { osgUtil::LineSegmentIntersector::Intersections intersections; std::string gdlist=""; float x = ea.getX(); float y = ea.getY(); if (view->computeIntersections(ea, intersections)) { for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin(); hitr != intersections.end(); ++hitr) { std::ostringstream os; if (!hitr->nodePath.empty() && !(hitr->nodePath.back()->getName().empty())) { // the geodes are identified by name. os<<"Object \""<nodePath.back()->getName()<<"\""<drawable.valid()) { os<<"Object \""<drawable->className()<<"\""<getLocalIntersectPoint()<<")"<<" normal("<getLocalIntersectNormal()<<")"<getWorldIntersectPoint()<<")"<<" normal("<getWorldIntersectNormal()<<")"<indexList; for(unsigned int i=0;igetName() << std::endl; if (event->getName() == "/pick-result") { std::string name(""); float x(0), y(0); event->getUserValue("name", name); event->getUserValue("x", x); event->getUserValue("y", y); std::ostringstream ss; ss << "Name: " << std::endl << name << std::endl << std::endl; ss << "x: " << y << " y: " << y << std::endl; _text->setText(ss.str()); return true; } else if(event->getName() == "/osgga") { osg::Vec4 rect; event->getUserValue("resize", rect); osgGA::EventVisitor* ev = dynamic_cast(nv); osg::View* view = ev ? dynamic_cast(ev->getActionAdapter()) : NULL; if (view && (rect[2] > 0) && (rect[3] > 0)) { OSG_ALWAYS << "resizing view to " << rect << std::endl; osgViewer::GraphicsWindow* win = view->getCamera()->getGraphicsContext() ? dynamic_cast(view->getCamera()->getGraphicsContext()) : NULL; if (win) win->setWindowRectangle(rect[2] + 10 + rect[0], rect[1], rect[2], rect[3]); } return true; } else { const osg::UserDataContainer* udc = event->getUserDataContainer(); if (udc) { OSG_ALWAYS << "contents of " << udc->getName() << ": " << std::endl; for(unsigned int i = 0; i < udc->getNumUserObjects(); ++i) { const osg::ValueObject* vo = dynamic_cast(udc->getUserObject(i)); OSG_ALWAYS << " " << vo->getName() << ": "; MyValueListVisitor vlv; vo->get(vlv); OSG_ALWAYS << vlv.value() << std::endl; } } return true; } return false; } osg::Node* createHUD() { // create the hud. derived from osgHud.cpp // adds a set of quads, each in a separate Geode - which can be picked individually // eg to be used as a menuing/help system! // Can pick texts too! osg::Camera* hudCamera = new osg::Camera; hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); hudCamera->setProjectionMatrixAsOrtho2D(0,1280,0,1024); hudCamera->setViewMatrix(osg::Matrix::identity()); hudCamera->setRenderOrder(osg::Camera::POST_RENDER); hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT); std::string timesFont("fonts/times.ttf"); // turn lighting off for the text and disable depth test to ensure its always ontop. osg::Vec3 position(150.0f,800.0f,0.0f); osg::Vec3 delta(0.0f,-60.0f,0.0f); { osg::Geode* geode = new osg::Geode(); osg::StateSet* stateset = geode->getOrCreateStateSet(); stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); geode->setName("simple"); hudCamera->addChild(geode); osgText::Text* text = new osgText::Text; geode->addDrawable( text ); text->setFont(timesFont); text->setText("Picking in Head Up Displays is simple!"); text->setPosition(position); position += delta; } for (int i=0; i<5; i++) { osg::Vec3 dy(0.0f,-30.0f,0.0f); osg::Vec3 dx(120.0f,0.0f,0.0f); osg::Geode* geode = new osg::Geode(); osg::StateSet* stateset = geode->getOrCreateStateSet(); const char *opts[]={"One", "Two", "Three", "January", "Feb", "2003"}; osg::Geometry *quad=new osg::Geometry; stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); std::string name="subOption"; name += " "; name += std::string(opts[i]); geode->setName(name); osg::Vec3Array* vertices = new osg::Vec3Array(4); // 1 quad osg::Vec4Array* colors = new osg::Vec4Array; colors = new osg::Vec4Array; colors->push_back(osg::Vec4(0.8-0.1*i,0.1*i,0.2*i, 1.0)); quad->setColorArray(colors, osg::Array::BIND_OVERALL); (*vertices)[0]=position; (*vertices)[1]=position+dx; (*vertices)[2]=position+dx+dy; (*vertices)[3]=position+dy; quad->setVertexArray(vertices); quad->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4)); geode->addDrawable(quad); hudCamera->addChild(geode); position += delta; } { // this displays what has been selected osg::Geode* geode = new osg::Geode(); osg::StateSet* stateset = geode->getOrCreateStateSet(); stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); geode->setName("The text label"); hudCamera->addChild(geode); position += delta; } return hudCamera; } class ForwardToDeviceEventHandler : public osgGA::EventHandler { public: ForwardToDeviceEventHandler(osgGA::Device* device) : osgGA::EventHandler(), _device(device) {} virtual bool handle(osgGA::Event* event, osg::Object* /*object*/, osg::NodeVisitor* /*nv*/) { _device->sendEvent(*event); return false; } protected: osg::ref_ptr _device; }; class OscServiceDiscoveredEventHandler: public ForwardToDeviceEventHandler { public: OscServiceDiscoveredEventHandler() : ForwardToDeviceEventHandler(NULL) {} virtual bool handle(osgGA::Event* event, osg::Object* object, osg::NodeVisitor* nv) { if (_device.valid()) return ForwardToDeviceEventHandler::handle(event, object, nv); if (event->getName() == "/zeroconf/service-added") { std::string host; unsigned int port; event->getUserValue("host", host); event->getUserValue("port", port); OSG_ALWAYS << "new osc-service discovered: " << host << ":" << port << std::endl; std::ostringstream ss ; ss << host << ":" << port << ".sender.osc"; _device = osgDB::readRefFile(ss.str()); osgGA::EventVisitor* ev = dynamic_cast(nv); osgViewer::View* view = ev ? dynamic_cast(ev->getActionAdapter()) : NULL; if (view) view->addEventHandler(new PickHandler(_device.get())); return true; } return false; } }; int main( int argc, char **argv ) { // use an ArgumentParser object to manage the program arguments. osg::ArgumentParser arguments(&argc,argv); arguments.getApplicationUsage()->addCommandLineOption("--zeroconf","uses zeroconf to advertise the osc-plugin and to discover it"); arguments.getApplicationUsage()->addCommandLineOption("--sender","create a view which sends its events via osc"); arguments.getApplicationUsage()->addCommandLineOption("--recevier","create a view which receive its events via osc"); // read the scene from the list of file specified commandline args. osg::ref_ptr scene = osgDB::readRefNodeFiles(arguments); if (!scene) { osg::Geode* geode = new osg::Geode(); osg::ShapeDrawable* drawable = new osg::ShapeDrawable(new osg::Box()); geode->addDrawable(drawable); scene = geode; } bool use_zeroconf(false); bool use_sender(false); bool use_receiver(false); if(arguments.find("--zeroconf") > 0) { use_zeroconf = true; } if(arguments.find("--sender") > 0) { use_sender = true; } if(arguments.find("--receiver") > 0) { use_receiver = true; } // construct the viewer. osgViewer::CompositeViewer viewer(arguments); // receiver view if (use_receiver) { osg::ref_ptr traits = new osg::GraphicsContext::Traits; traits->x = 600; traits->y = 100; traits->width = 400; traits->height = 400; traits->windowDecoration = true; traits->doubleBuffer = true; traits->sharedContext = 0; traits->windowName = "Receiver / view two"; osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); osgViewer::View* view = new osgViewer::View; view->setName("View two"); viewer.addView(view); osg::Group* group = new osg::Group(); group->addChild(scene.get()); osg::Geode* geode = new osg::Geode(); group->addChild(geode); osgText::Text* text = new osgText::Text(); geode->addDrawable( text ); text->setFont("Arial.ttf"); text->setText("Waiting for data"); text->setPosition(osg::Vec3(-50,0,30)); text->setAxisAlignment(osgText::TextBase::SCREEN); text->setDataVariance(osg::Object::DYNAMIC); text->setCharacterSize(2.0f); view->setSceneData(group); view->getCamera()->setName("Cam two"); view->getCamera()->setViewport(new osg::Viewport(0,0, traits->width, traits->height)); view->getCamera()->setGraphicsContext(gc.get()); view->addEventHandler( new osgViewer::StatsHandler ); view->addEventHandler( new UserEventHandler(text) ); osg::ref_ptr device = osgDB::readRefFile("0.0.0.0:9000.receiver.osc"); if (device.valid() && (device->getCapabilities() & osgGA::Device::RECEIVE_EVENTS)) { view->addDevice(device); // add a zeroconf device, advertising the osc-device if(use_zeroconf) { osg::ref_ptr zeroconf_device = osgDB::readRefFile("_osc._udp:9000.advertise.zeroconf"); if (zeroconf_device) { view->addDevice(zeroconf_device); } } } else { OSG_WARN << "could not open osc-device, receiving will not work" << std::endl; } } // sender view if(use_sender) { osg::ref_ptr traits = new osg::GraphicsContext::Traits; traits->x = 100; traits->y = 100; traits->width = 400; traits->height = 400; traits->windowDecoration = true; traits->doubleBuffer = true; traits->sharedContext = 0; traits->windowName = "Sender / view one"; osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); #ifdef __APPLE__ // as multitouch is disabled by default, enable it now osgViewer::GraphicsWindowCocoa* win = dynamic_cast(gc.get()); if (win) win->setMultiTouchEnabled(true); #endif osgViewer::View* view = new osgViewer::View; view->setName("View one"); viewer.addView(view); osg::Group* g = new osg::Group(); g->addChild(scene.get()); g->addChild(createHUD()); view->setSceneData(g); view->getCamera()->setName("Cam one"); view->getCamera()->setViewport(new osg::Viewport(0,0, traits->width, traits->height)); view->getCamera()->setGraphicsContext(gc.get()); view->setCameraManipulator(new osgGA::TrackballManipulator); // add the state manipulator osg::ref_ptr statesetManipulator = new osgGA::StateSetManipulator; statesetManipulator->setStateSet(view->getCamera()->getOrCreateStateSet()); view->addEventHandler( statesetManipulator.get() ); view->addEventHandler( new osgViewer::StatsHandler ); if (use_zeroconf) { osg::ref_ptr zeroconf_device = osgDB::readRefFile("_osc._udp.discover.zeroconf"); if(zeroconf_device) { view->addDevice(zeroconf_device); view->getEventHandlers().push_front(new OscServiceDiscoveredEventHandler()); } } else { osg::ref_ptr device = osgDB::readRefFile("localhost:9000.sender.osc"); if (device.valid() && (device->getCapabilities() & osgGA::Device::SEND_EVENTS)) { // add as first event handler, so it gets ALL events ... view->getEventHandlers().push_front(new ForwardToDeviceEventHandler(device.get())); // add the demo-pick-event-handler view->addEventHandler(new PickHandler(device.get())); } else { OSG_WARN << "could not open osc-device, sending will not work" << std::endl; } } } while (arguments.read("-s")) { viewer.setThreadingModel(osgViewer::CompositeViewer::SingleThreaded); } while (arguments.read("-g")) { viewer.setThreadingModel(osgViewer::CompositeViewer::CullDrawThreadPerContext); } while (arguments.read("-c")) { viewer.setThreadingModel(osgViewer::CompositeViewer::CullThreadPerCameraDrawThreadPerContext); } // run the viewer's main frame loop return viewer.run(); }