OSGWidget.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // Include own headers
  2. #include "OSGWidget.hpp"
  3. #include "PickHandler.hpp"
  4. // Include dependencies
  5. #include <osgViewer/Viewer>
  6. #include <osg/ShapeDrawable>
  7. #include <osg/Geode>
  8. #include <osgDB/ReadFile>
  9. #include <osg/Group>
  10. #include <osg/Switch>
  11. #include <osg/MatrixTransform>
  12. #include <osg/Matrix>
  13. #include <osgGA/TrackballManipulator>
  14. #include <osgUtil/LineSegmentIntersector>
  15. #include <osgUtil/IntersectionVisitor>
  16. #include <osg/PolygonMode>
  17. #include <osgDB/WriteFile>
  18. #include <osg/Material>
  19. #include <osg/StateSet>
  20. #include <cassert>
  21. #include <stdexcept>
  22. #include <vector>
  23. #include <QDebug>
  24. #include <QKeyEvent>
  25. #include <QPainter>
  26. #include <QWheelEvent>
  27. namespace osgWidget {
  28. void Viewer::setupThreading() {
  29. if (_threadingModel == SingleThreaded) {
  30. if (_threadsRunning) {
  31. stopThreading();
  32. }
  33. } else {
  34. if (!_threadsRunning) {
  35. startThreading();
  36. }
  37. }
  38. }
  39. }
  40. OSGWidget::OSGWidget(QWidget* parent): QOpenGLWidget(parent),
  41. graphicsWindow_(new osgViewer::GraphicsWindowEmbedded(this->x(), this->y(), this->width(), this->height())),
  42. _viewer(new osgWidget::Viewer),
  43. selectionActive_(false),
  44. selectionFinished_(true)
  45. {
  46. this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  47. // Root node of the scene
  48. _root = new osg::Group;
  49. // Create the camera
  50. float aspectRatio = static_cast<float>(this->width()) / static_cast<float>(this->height());
  51. auto pixelRatio = this->devicePixelRatio();
  52. osg::Camera* camera = new osg::Camera;
  53. camera->setViewport(0, 0, this->width() * pixelRatio, this->height() * pixelRatio);
  54. camera->setClearColor(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
  55. camera->setProjectionMatrixAsPerspective(30.0f, aspectRatio, 1.0f, 1000.0f);
  56. camera->setGraphicsContext(graphicsWindow_);
  57. // Create the viewer
  58. _view = new osgViewer::View;
  59. _view->setCamera(camera);
  60. _view->setSceneData(_root);
  61. // Add axesNode under root
  62. _axesNode = osgDB::readNodeFile("../../testdata/testbutton.stl");
  63. if (!_axesNode) {
  64. printf("Origin node not loaded, model not found\n");
  65. }
  66. // Set material for basic lighting and enable depth tests. Else, the sphere
  67. // will suffer from rendering errors.
  68. {
  69. osg::StateSet* stateSet = _axesNode->getOrCreateStateSet();
  70. osg::Material* material = new osg::Material;
  71. material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
  72. stateSet->setAttributeAndModes(material, osg::StateAttribute::ON);
  73. stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
  74. }
  75. _root->addChild(_axesNode);
  76. // Attach a manipulator (it's usually done for us when we use viewer.run())
  77. osg::ref_ptr<osgGA::TrackballManipulator> tm = new osgGA::TrackballManipulator;
  78. tm->setAllowThrow(false);
  79. _view->setCameraManipulator(tm);
  80. _viewer->addView(_view);
  81. _viewer->setThreadingModel(osgViewer::CompositeViewer::SingleThreaded);
  82. _viewer->realize();
  83. _storeHandler = new StoreHandler(_root);
  84. _openScadRenderer = new OpenScadRenderer();
  85. _threeMFWriter = new ThreeMFWriter();
  86. osg::ref_ptr<PickHandler> picker = new PickHandler(_storeHandler, _openScadRenderer, _threeMFWriter, _axesNode);
  87. _root->addChild(picker->getOrCreateSelectionCylinder());
  88. _view->addEventHandler(picker.get());
  89. // This ensures that the widget will receive keyboard events. This focus
  90. // policy is not set by default. The default, Qt::NoFocus, will result in
  91. // keyboard events that are ignored.
  92. this->setFocusPolicy(Qt::StrongFocus);
  93. this->setMinimumSize(100, 100);
  94. // Ensures that the widget receives mouse move events even though no
  95. // mouse button has been pressed. We require this in order to let the
  96. // graphics window switch viewports properly.
  97. this->setMouseTracking(true);
  98. }
  99. OSGWidget::~OSGWidget() {
  100. }
  101. void OSGWidget::paintEvent(QPaintEvent*) {
  102. this->makeCurrent();
  103. QPainter painter(this);
  104. painter.setRenderHint(QPainter::Antialiasing);
  105. this->paintGL();
  106. painter.end();
  107. this->doneCurrent();
  108. }
  109. void OSGWidget::paintGL() {
  110. _viewer->frame();
  111. }
  112. void OSGWidget::resizeGL(int width, int height) {
  113. this->getEventQueue()->windowResize(this->x(), this->y(), width, height);
  114. graphicsWindow_->resized(this->x(), this->y(), width, height);
  115. this->onResize(width, height);
  116. }
  117. void OSGWidget::keyPressEvent(QKeyEvent* event) {
  118. QString keyString = event->text();
  119. const char* keyData = keyString.toLocal8Bit().data();
  120. if (event->key() == Qt::Key_H) {
  121. this->onHome();
  122. return;
  123. }
  124. this->getEventQueue()->keyPress(osgGA::GUIEventAdapter::KeySymbol(*keyData));
  125. }
  126. void OSGWidget::keyReleaseEvent(QKeyEvent* event) {
  127. QString keyString = event->text();
  128. const char* keyData = keyString.toLocal8Bit().data();
  129. this->getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KeySymbol(*keyData));
  130. }
  131. void OSGWidget::mouseMoveEvent(QMouseEvent* event) {
  132. auto pixelRatio = this->devicePixelRatio();
  133. this->getEventQueue()->mouseMotion(static_cast<float>(event->position().x() * pixelRatio), static_cast<float>(event->position().y() * pixelRatio));
  134. }
  135. void OSGWidget::mousePressEvent(QMouseEvent* event) {
  136. unsigned int button = 0;
  137. switch(event->button()) {
  138. case Qt::LeftButton:
  139. button = 1;
  140. break;
  141. case Qt::MiddleButton:
  142. button = 2;
  143. break;
  144. case Qt::RightButton:
  145. button = 3;
  146. break;
  147. default:
  148. break;
  149. }
  150. auto pixelRatio = this->devicePixelRatio();
  151. this->getEventQueue()->mouseButtonPress(static_cast<float>(event->position().x() * pixelRatio), static_cast<float>(event->position().y() * pixelRatio), button);
  152. }
  153. void OSGWidget::mouseReleaseEvent(QMouseEvent* event) {
  154. unsigned int button = 0;
  155. switch(event->button()) {
  156. case Qt::LeftButton:
  157. button = 1;
  158. break;
  159. case Qt::MiddleButton:
  160. button = 2;
  161. break;
  162. case Qt::RightButton:
  163. button = 3;
  164. break;
  165. default:
  166. break;
  167. }
  168. auto pixelRatio = this->devicePixelRatio();
  169. this->getEventQueue()->mouseButtonRelease(static_cast<float>(pixelRatio * event->position().x()), static_cast<float>(pixelRatio * event->position().y()), button);
  170. }
  171. void OSGWidget::wheelEvent(QWheelEvent* event) {
  172. event->accept();
  173. int delta = event->angleDelta().y();
  174. osgGA::GUIEventAdapter::ScrollingMotion motion = delta > 0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN;
  175. this->getEventQueue()->mouseScroll(motion);
  176. }
  177. bool OSGWidget::event(QEvent* event) {
  178. bool handled = QOpenGLWidget::event(event);
  179. // This ensures that the OSG widget is always going to be repainted after the
  180. // user performed some interaction. Doing this in the event handler ensures
  181. // that we don't forget about some event and prevents duplicate code.
  182. switch(event->type()) {
  183. case QEvent::KeyPress:
  184. case QEvent::KeyRelease:
  185. case QEvent::MouseButtonDblClick:
  186. case QEvent::MouseButtonPress:
  187. case QEvent::MouseButtonRelease:
  188. case QEvent::MouseMove:
  189. case QEvent::Wheel:
  190. this->update();
  191. break;
  192. case QEvent::Resize:
  193. this->onResize(this->width(), this->height());
  194. break;
  195. default:
  196. break;
  197. }
  198. return handled;
  199. }
  200. void OSGWidget::onHome() {
  201. osgViewer::ViewerBase::Views views;
  202. _viewer->getViews( views );
  203. for(std::size_t i = 0; i < views.size(); i++) {
  204. osgViewer::View* view = views.at(i);
  205. view->home();
  206. }
  207. }
  208. void OSGWidget::onResize(int width, int height) {
  209. std::vector<osg::Camera*> cameras;
  210. _viewer->getCameras(cameras);
  211. assert(cameras.size() == 1);
  212. auto pixelRatio = this->devicePixelRatio();
  213. cameras[0]->setViewport(0, 0, width * pixelRatio, height * pixelRatio);
  214. }
  215. osgGA::EventQueue* OSGWidget::getEventQueue() const {
  216. osgGA::EventQueue* eventQueue = graphicsWindow_->getEventQueue();
  217. if (eventQueue) {
  218. return eventQueue;
  219. } else {
  220. throw std::runtime_error("Unable to obtain valid event queue");
  221. }
  222. }