OSGWidget.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. // Include own headers
  2. #include "OSGWidget.hpp"
  3. // Include modules
  4. #include "PickHandler.hpp"
  5. #include "TrackPointRenderer.hpp"
  6. // Include dependencies
  7. #include <osgViewer/Viewer>
  8. #include <osg/ShapeDrawable>
  9. #include <osg/Geode>
  10. #include <osgDB/ReadFile>
  11. #include <osg/Group>
  12. #include <osg/Switch>
  13. #include <osg/MatrixTransform>
  14. #include <osg/Matrix>
  15. #include <osgGA/TrackballManipulator>
  16. #include <osgUtil/LineSegmentIntersector>
  17. #include <osgUtil/IntersectionVisitor>
  18. #include <osgUtil/MeshOptimizers>
  19. #include <osg/PolygonMode>
  20. #include <osgDB/WriteFile>
  21. #include <osg/Material>
  22. #include <osg/StateSet>
  23. #include <cassert>
  24. #include <stdexcept>
  25. #include <vector>
  26. #include <QDebug>
  27. #include <QKeyEvent>
  28. #include <QPainter>
  29. #include <QWheelEvent>
  30. namespace osgWidget {
  31. void Viewer::setupThreading() {
  32. if (_threadingModel == SingleThreaded) {
  33. if (_threadsRunning) {
  34. stopThreading();
  35. }
  36. } else {
  37. if (!_threadsRunning) {
  38. startThreading();
  39. }
  40. }
  41. }
  42. }
  43. void OSGWidget::fixMaterialState(osg::ref_ptr<osg::Node> node) {
  44. osg::StateSet* stateSet = node->getOrCreateStateSet();
  45. osg::Material* material = new osg::Material;
  46. material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
  47. stateSet->setAttributeAndModes(material, osg::StateAttribute::ON);
  48. stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
  49. }
  50. OSGWidget::OSGWidget(QWidget* parent): QOpenGLWidget(parent),
  51. graphicsWindow_(new osgViewer::GraphicsWindowEmbedded(this->x(), this->y(), this->width(), this->height())),
  52. _viewer(new osgWidget::Viewer),
  53. selectionActive_(false),
  54. selectionFinished_(true)
  55. {
  56. this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  57. // Root node of the scene
  58. _root = new osg::Group;
  59. // Create the camera
  60. float aspectRatio = static_cast<float>(this->width()) / static_cast<float>(this->height());
  61. auto pixelRatio = this->devicePixelRatio();
  62. osg::Camera* camera = new osg::Camera;
  63. camera->setViewport(0, 0, this->width() * pixelRatio, this->height() * pixelRatio);
  64. camera->setClearColor(osg::Vec4(0.2f, 0.1875f, 0.375f, 1.0f));
  65. camera->setProjectionMatrixAsPerspective(30.0f, aspectRatio, 1.0f, 1000.0f);
  66. camera->setGraphicsContext(graphicsWindow_);
  67. // Create the viewer
  68. _view = new osgViewer::View;
  69. _view->setCamera(camera);
  70. _view->setSceneData(_root);
  71. // Create coordinate axes
  72. _coordinateAxes = new osg::Group;
  73. osg::ref_ptr<osg::MatrixTransform> xRotation = new osg::MatrixTransform;
  74. xRotation->setMatrix(osg::Matrix::rotate(osg::Vec3f(0.0f, 0.0f, 1.0f), osg::Vec3f(1.0f, 0.0f, 0.0f)));
  75. osg::ref_ptr<osg::Geode> xAxis = new osg::Geode;
  76. osg::ref_ptr<osg::ShapeDrawable> xAxisShape = new osg::ShapeDrawable();
  77. xAxisShape->setShape(new osg::Cylinder(osg::Vec3(0.0f, 0.0f, 0.0f), 0.05f, 100.0f));
  78. xAxisShape->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
  79. xAxis->addDrawable(xAxisShape.get());
  80. xRotation->addChild(xAxis.get());
  81. osg::ref_ptr<osg::MatrixTransform> yRotation = new osg::MatrixTransform;
  82. yRotation->setMatrix(osg::Matrix::rotate(osg::Vec3f(0.0f, 0.0f, 1.0f), osg::Vec3f(0.0f, 1.0f, 0.0f)));
  83. osg::ref_ptr<osg::Geode> yAxis = new osg::Geode;
  84. osg::ref_ptr<osg::ShapeDrawable> yAxisShape = new osg::ShapeDrawable();
  85. yAxisShape->setShape(new osg::Cylinder(osg::Vec3(0.0f, 0.0f, 0.0f), 0.05f, 100.0f));
  86. yAxisShape->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
  87. yAxis->addDrawable(yAxisShape.get());
  88. yRotation->addChild(yAxis.get());
  89. osg::ref_ptr<osg::Geode> zAxis = new osg::Geode;
  90. osg::ref_ptr<osg::ShapeDrawable> zAxisShape = new osg::ShapeDrawable();
  91. zAxisShape->setShape(new osg::Cylinder(osg::Vec3(0.0f, 0.0f, 0.0f), 0.05f, 100.0f));
  92. zAxisShape->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
  93. zAxis->addDrawable(zAxisShape.get());
  94. _coordinateAxes->addChild(xRotation.get());
  95. _coordinateAxes->addChild(yRotation.get());
  96. _coordinateAxes->addChild(zAxis.get());
  97. OSGWidget::fixMaterialState(_coordinateAxes);
  98. _root->addChild(_coordinateAxes);
  99. _mesh = new osg::Geode;
  100. // Attach a manipulator (it's usually done for us when we use viewer.run())
  101. osg::ref_ptr<osgGA::TrackballManipulator> tm = new osgGA::TrackballManipulator;
  102. tm->setAllowThrow(false);
  103. _view->setCameraManipulator(tm);
  104. _viewer->addView(_view);
  105. _viewer->setThreadingModel(osgViewer::CompositeViewer::SingleThreaded);
  106. _viewer->realize();
  107. _picker = new PickHandler(this, _root);
  108. _root->addChild(_picker->getPickerRoot());
  109. _view->addEventHandler(_picker);
  110. // This ensures that the widget will receive keyboard events. This focus
  111. // policy is not set by default. The default, Qt::NoFocus, will result in
  112. // keyboard events that are ignored.
  113. this->setFocusPolicy(Qt::StrongFocus);
  114. this->setMinimumSize(100, 100);
  115. // Ensures that the widget receives mouse move events even though no
  116. // mouse button has been pressed. We require this in order to let the
  117. // graphics window switch viewports properly.
  118. this->setMouseTracking(true);
  119. _pointRoot = new osg::Group;
  120. _root->addChild(_pointRoot.get());
  121. _pointRenderer = new TrackPointRenderer(this, _pointRoot);
  122. }
  123. OSGWidget::~OSGWidget() {
  124. }
  125. void OSGWidget::renderBaseMesh(const osg::ref_ptr<osg::Vec3Array> vertices, const osg::ref_ptr<osg::Vec3Array> normals) {
  126. _root->removeChild(_mesh);
  127. osg::ref_ptr<osg::Geometry> meshGeometry = new osg::Geometry;
  128. meshGeometry->setVertexArray(vertices.get());
  129. meshGeometry->setNormalArray(normals.get(), osg::Array::BIND_PER_VERTEX);
  130. meshGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, vertices->getNumElements()));
  131. osgUtil::optimizeMesh(meshGeometry.get());
  132. _mesh->addDrawable(meshGeometry.get());
  133. OSGWidget::fixMaterialState(_mesh);
  134. _root->addChild(_mesh);
  135. _picker->updateRenderer();
  136. }
  137. osg::ref_ptr<osg::Geode> OSGWidget::getMesh() {
  138. return _mesh;
  139. }
  140. PickHandler* OSGWidget::getPicker() {
  141. return _picker;
  142. }
  143. TrackPointRenderer* OSGWidget::getPointRenderer() {
  144. return _pointRenderer;
  145. }
  146. void OSGWidget::paintEvent(QPaintEvent*) {
  147. this->makeCurrent();
  148. QPainter painter(this);
  149. painter.setRenderHint(QPainter::Antialiasing);
  150. this->paintGL();
  151. painter.end();
  152. this->doneCurrent();
  153. }
  154. void OSGWidget::paintGL() {
  155. _viewer->frame();
  156. }
  157. void OSGWidget::resizeGL(int width, int height) {
  158. auto pixelRatio = this->devicePixelRatio();
  159. this->getEventQueue()->windowResize(this->x(), this->y(), width * pixelRatio, height * pixelRatio);
  160. graphicsWindow_->resized(this->x(), this->y(), width * pixelRatio, height * pixelRatio);
  161. this->onResize(width, height);
  162. }
  163. void OSGWidget::keyPressEvent(QKeyEvent* event) {
  164. QString keyString = event->text();
  165. const char* keyData = keyString.toLocal8Bit().data();
  166. if (event->key() == Qt::Key_H) {
  167. this->onHome();
  168. return;
  169. }
  170. this->getEventQueue()->keyPress(osgGA::GUIEventAdapter::KeySymbol(*keyData));
  171. }
  172. void OSGWidget::keyReleaseEvent(QKeyEvent* event) {
  173. QString keyString = event->text();
  174. const char* keyData = keyString.toLocal8Bit().data();
  175. this->getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KeySymbol(*keyData));
  176. }
  177. void OSGWidget::mouseMoveEvent(QMouseEvent* event) {
  178. auto pixelRatio = this->devicePixelRatio();
  179. this->getEventQueue()->mouseMotion(static_cast<float>(event->position().x() * pixelRatio), static_cast<float>(event->position().y() * pixelRatio));
  180. }
  181. void OSGWidget::mousePressEvent(QMouseEvent* event) {
  182. unsigned int button = 0;
  183. switch(event->button()) {
  184. case Qt::LeftButton:
  185. button = 1;
  186. break;
  187. case Qt::MiddleButton:
  188. button = 2;
  189. break;
  190. case Qt::RightButton:
  191. button = 3;
  192. break;
  193. default:
  194. break;
  195. }
  196. auto pixelRatio = this->devicePixelRatio();
  197. this->getEventQueue()->mouseButtonPress(static_cast<float>(event->position().x() * pixelRatio), static_cast<float>(event->position().y() * pixelRatio), button);
  198. }
  199. void OSGWidget::mouseReleaseEvent(QMouseEvent* event) {
  200. unsigned int button = 0;
  201. switch(event->button()) {
  202. case Qt::LeftButton:
  203. button = 1;
  204. break;
  205. case Qt::MiddleButton:
  206. button = 2;
  207. break;
  208. case Qt::RightButton:
  209. button = 3;
  210. break;
  211. default:
  212. break;
  213. }
  214. auto pixelRatio = this->devicePixelRatio();
  215. this->getEventQueue()->mouseButtonRelease(static_cast<float>(event->position().x() * pixelRatio), static_cast<float>(event->position().y() * pixelRatio), button);
  216. }
  217. void OSGWidget::wheelEvent(QWheelEvent* event) {
  218. event->accept();
  219. int delta = event->angleDelta().y();
  220. osgGA::GUIEventAdapter::ScrollingMotion motion = delta > 0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN;
  221. this->getEventQueue()->mouseScroll(motion);
  222. }
  223. bool OSGWidget::event(QEvent* event) {
  224. bool handled = QOpenGLWidget::event(event);
  225. // This ensures that the OSG widget is always going to be repainted after the
  226. // user performed some interaction. Doing this in the event handler ensures
  227. // that we don't forget about some event and prevents duplicate code.
  228. switch(event->type()) {
  229. case QEvent::KeyPress:
  230. case QEvent::KeyRelease:
  231. case QEvent::MouseButtonDblClick:
  232. case QEvent::MouseButtonPress:
  233. case QEvent::MouseButtonRelease:
  234. case QEvent::MouseMove:
  235. case QEvent::Wheel:
  236. this->update();
  237. break;
  238. case QEvent::Resize:
  239. this->onResize(this->width(), this->height());
  240. break;
  241. default:
  242. break;
  243. }
  244. return handled;
  245. }
  246. void OSGWidget::onHome() {
  247. osgViewer::ViewerBase::Views views;
  248. _viewer->getViews( views );
  249. for(std::size_t i = 0; i < views.size(); i++) {
  250. osgViewer::View* view = views.at(i);
  251. view->home();
  252. }
  253. }
  254. void OSGWidget::onResize(int width, int height) {
  255. std::vector<osg::Camera*> cameras;
  256. _viewer->getCameras(cameras);
  257. assert(cameras.size() == 1);
  258. auto pixelRatio = this->devicePixelRatio();
  259. cameras[0]->setViewport(0, 0, width * pixelRatio, height * pixelRatio);
  260. }
  261. osgGA::EventQueue* OSGWidget::getEventQueue() const {
  262. osgGA::EventQueue* eventQueue = graphicsWindow_->getEventQueue();
  263. if (eventQueue) {
  264. return eventQueue;
  265. } else {
  266. throw std::runtime_error("Unable to obtain valid event queue");
  267. }
  268. }