| 123 | | float mx() { return _mx; } |
| 124 | | float my() { return _my; } |
| 125 | | unsigned int mbutton() { return _mbutton; } |
| 126 | | |
| 127 | | void resetTrackball() |
| 128 | | { |
| 129 | | osg::Node* scene = _sceneView->getSceneData(); |
| 130 | | if (scene) |
| 131 | | { |
| 132 | | const osg::BoundingSphere& bs = scene->getBound(); |
| 133 | | if (bs.valid()) |
| 134 | | { |
| 135 | | _trackBall->reset(); |
| 136 | | _trackBall->setOrientation( Producer::Trackball::Z_UP ); |
| 137 | | _trackBall->setDistance(bs.radius()*2.0f); |
| 138 | | _trackBall->translate(-bs.center().x(),-bs.center().y(),-bs.center().z()); |
| 139 | | } |
| 140 | | } |
| 141 | | } |
| 142 | | |
| 143 | | osg::Matrixd getViewMatrix() |
| 144 | | { |
| 145 | | _trackBall->input( mx(), my(), mbutton() ); |
| 146 | | return osg::Matrixd(_trackBall->getMatrix().ptr()); |
| 147 | | } |
| 148 | | |
| 149 | | void pick(float x, float y) |
| 150 | | { |
| 151 | | osg::Node* scene = _sceneView->getSceneData(); |
| 152 | | if (scene) |
| 153 | | { |
| 154 | | std::cout<<"Picking "<<x<<"\t"<<y<<std::endl; |
| 155 | | |
| 156 | | int origX, origY, width, height; |
| 157 | | _sceneView->getViewport(origX,origY,width,height); |
| 158 | | |
| 159 | | // convert Producer's non dimensional x,y coords back into pixel coords. |
| 160 | | int pixel_x = (int)((x+1.0f)*0.5f*(float)width); |
| 161 | | int pixel_y = (int)((y+1.0f)*0.5f*(float)height); |
| 162 | | |
| 163 | | |
| 164 | | osgUtil::PickVisitor pick(_sceneView->getViewport(), |
| 165 | | _sceneView->getProjectionMatrix(), |
| 166 | | _sceneView->getViewMatrix(), |
| 167 | | pixel_x, pixel_y); |
| 168 | | |
| 169 | | scene->accept(pick); |
| 170 | | |
| 171 | | osgUtil::PickVisitor::LineSegmentHitListMap& segHitList = pick.getSegHitList(); |
| 172 | | if (!segHitList.empty() && !segHitList.begin()->second.empty()) |
| 173 | | { |
| 174 | | std::cout<<"Got hits"<<std::endl; |
| 175 | | |
| 176 | | // get the hits for the first segment |
| 177 | | osgUtil::PickVisitor::HitList& hits = segHitList.begin()->second; |
| 178 | | |
| 179 | | // just take the first hit - nearest the eye point. |
| 180 | | osgUtil::Hit& hit = hits.front(); |
| 181 | | |
| 182 | | osg::NodePath& nodePath = hit._nodePath; |
| 183 | | osg::Node* node = (nodePath.size()>=1)?nodePath[nodePath.size()-1]:0; |
| 184 | | osg::Group* parent = (nodePath.size()>=2)?dynamic_cast<osg::Group*>(nodePath[nodePath.size()-2]):0; |
| 185 | | |
| 186 | | if (node) std::cout<<" Hits "<<node->className()<<" nodePath size"<<nodePath.size()<<std::endl; |
| 187 | | |
| 188 | | // now we try to decorate the hit node by the osgFX::Scribe to show that its been "picked" |
| 189 | | if (parent && node) |
| 190 | | { |
| 191 | | |
| 192 | | std::cout<<" parent "<<parent->className()<<std::endl; |
| 193 | | |
| 194 | | osgFX::Scribe* parentAsScribe = dynamic_cast<osgFX::Scribe*>(parent); |
| 195 | | if (!parentAsScribe) |
| 196 | | { |
| 197 | | // node not already picked, so highlight it with an osgFX::Scribe |
| 198 | | osgFX::Scribe* scribe = new osgFX::Scribe(); |
| 199 | | scribe->addChild(node); |
| 200 | | parent->replaceChild(node,scribe); |
| 201 | | } |
| 202 | | else |
| 203 | | { |
| 204 | | // node already picked so we want to remove scribe to unpick it. |
| 205 | | osg::Node::ParentList parentList = parentAsScribe->getParents(); |
| 206 | | for(osg::Node::ParentList::iterator itr=parentList.begin(); |
| 207 | | itr!=parentList.end(); |
| 208 | | ++itr) |
| 209 | | { |
| 210 | | (*itr)->replaceChild(parentAsScribe,node); |
| 211 | | } |
| 212 | | } |
| 213 | | } |
| 214 | | |
| 215 | | } |
| 216 | | |
| 217 | | } |
| 218 | | |
| 219 | | } |
| 220 | | |
| 221 | | void saveSelectedModel() |
| 222 | | { |
| 223 | | CreateModelToSaveVisitor cmtsv; |
| 224 | | _sceneView->getSceneData()->accept(cmtsv); |
| 225 | | |
| 226 | | if (cmtsv._group->getNumChildren()>0) |
| 227 | | { |
| 228 | | osgDB::writeNodeFile(*cmtsv._group, "selected_model.osg"); |
| 229 | | } |
| 230 | | } |
| 279 | | osg::ref_ptr<MyKeyboardMouseCallback> kbmcb = new MyKeyboardMouseCallback(sceneView.get()); |
| 280 | | |
| | 142 | osg::ref_ptr<MyKeyboardMouseCallback> kbmcb = new MyKeyboardMouseCallback(eventQueue.get()); |
| | 143 | |
| | 144 | // create a tracball manipulator to move the camera around in response to keyboard/mouse events |
| | 145 | osg::ref_ptr<osgGA::TrackballManipulator> cameraManipulator = new osgGA::TrackballManipulator; |
| | 146 | |
| | 147 | // keep a list of event handlers to manipulate the application/scene with in response to keyboard/mouse events |
| | 148 | typedef std::list< osg::ref_ptr<osgGA::GUIEventHandler> > EventHandlers; |
| | 149 | EventHandlers eventHandlers; |
| | 150 | |
| | 151 | osg::ref_ptr<osgGA::StateSetManipulator> statesetManipulator = new osgGA::StateSetManipulator; |
| | 152 | statesetManipulator->setStateSet(sceneView->getGlobalStateSet()); |
| | 153 | eventHandlers.push_back(statesetManipulator.get()); |
| | 154 | |
| | 155 | // create an event visitor to pass the events down to the scene graph nodes |
| | 156 | osg::ref_ptr<osgGA::EventVisitor> eventVisitor = new osgGA::EventVisitor; |
| | 157 | |
| | 158 | // create an action adapter to allow event handlers to request actions from the GUI. |
| | 159 | osg::ref_ptr<MyActionAdapter> actionAdapter = new MyActionAdapter; |
| | 165 | |
| | 166 | eventQueue->setStartTick(start_tick); |
| | 167 | |
| | 168 | // set the mouse input range (note WindowSize name in appropriate here so osgGA::GUIEventAdapter API really needs looking at, Robert Osfield, June 2006). |
| | 169 | // Producer defaults to using non-dimensional units, so we pass this onto osgGA, most windowing toolkits use pixel coords so use the window size instead. |
| | 170 | eventQueue->getCurrentEventState()->setWindowSize(-1.0, -1.0, 1.0, 1.0); |
| | 171 | |
| | 172 | |
| | 173 | // home the manipulator. |
| | 174 | osg::ref_ptr<osgGA::GUIEventAdapter> dummyEvent = eventQueue->createEvent(); |
| | 175 | cameraManipulator->setNode(sceneView->getSceneData()); |
| | 176 | cameraManipulator->home(*dummyEvent, *actionAdapter); |
| | 177 | |
| 301 | | // set the view |
| 302 | | sceneView->setViewMatrix(kbmcb->getViewMatrix()); |
| | 193 | // create an event to signal the new frame. |
| | 194 | eventQueue->frame(frameStamp->getReferenceTime()); |
| | 195 | |
| | 196 | // get the event since the last frame. |
| | 197 | osgGA::EventQueue::Events events; |
| | 198 | eventQueue->takeEvents(events); |
| | 199 | |
| | 200 | if (eventVisitor.valid()) |
| | 201 | { |
| | 202 | eventVisitor->setTraversalNumber(frameStamp->getFrameNumber()); |
| | 203 | } |
| | 204 | |
| | 205 | // dispatch the events in order of arrival. |
| | 206 | for(osgGA::EventQueue::Events::iterator event_itr = events.begin(); |
| | 207 | event_itr != events.end(); |
| | 208 | ++event_itr) |
| | 209 | { |
| | 210 | bool handled = false; |
| | 211 | |
| | 212 | if (eventVisitor.valid() && sceneView->getSceneData()) |
| | 213 | { |
| | 214 | eventVisitor->reset(); |
| | 215 | eventVisitor->addEvent(event_itr->get()); |
| | 216 | sceneView->getSceneData()->accept(*eventVisitor); |
| | 217 | if (eventVisitor->getEventHandled()) |
| | 218 | handled = true; |
| | 219 | } |
| | 220 | |
| | 221 | if (cameraManipulator.valid() && !handled) |
| | 222 | { |
| | 223 | /*handled =*/ cameraManipulator->handle(*(*event_itr), *actionAdapter); |
| | 224 | } |
| | 225 | |
| | 226 | for(EventHandlers::iterator handler_itr=eventHandlers.begin(); |
| | 227 | handler_itr!=eventHandlers.end() && !handled; |
| | 228 | ++handler_itr) |
| | 229 | { |
| | 230 | handled = (*handler_itr)->handle(*(*event_itr),*actionAdapter,0,0); |
| | 231 | } |
| | 232 | |
| | 233 | // osg::notify(osg::NOTICE)<<" Handled event "<<(*event_itr)->getTime()<<" "<< handled<<std::endl; |
| | 234 | |
| | 235 | } |
| | 236 | |
| | 237 | |
| | 238 | // update view matrices |
| | 239 | if (cameraManipulator.valid()) |
| | 240 | { |
| | 241 | sceneView->setViewMatrix(cameraManipulator->getInverseMatrix()); |
| | 242 | } |