mainwindow.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /// \file mainwindow.hpp
  2. /// \brief Main window and algorhytms.
  3. /// \author [email protected]
  4. /// \date 2016
  5. #include "mainwindow.hpp"
  6. #include "ui_mainwindow.h"
  7. // Header files, Assimp.
  8. #include <assimp/Exporter.hpp>
  9. #include <assimp/postprocess.h>
  10. #ifndef __unused
  11. #define __unused __attribute__((unused))
  12. #endif // __unused
  13. /**********************************/
  14. /************ Functions ***********/
  15. /**********************************/
  16. /********************************************************************/
  17. /********************* Import/Export functions **********************/
  18. /********************************************************************/
  19. void MainWindow::ImportFile(const QString &pFileName)
  20. {
  21. using namespace Assimp;
  22. QTime time_begin = QTime::currentTime();
  23. if(mScene != nullptr)
  24. {
  25. mImporter.FreeScene();
  26. mGLView->FreeScene();
  27. }
  28. // Try to import scene.
  29. mScene = mImporter.ReadFile(pFileName.toStdString(), aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_ValidateDataStructure | \
  30. aiProcess_GenUVCoords | aiProcess_TransformUVCoords | aiProcess_FlipUVs);
  31. if(mScene != nullptr)
  32. {
  33. ui->lblLoadTime->setText(QString("%1").arg(time_begin.secsTo(QTime::currentTime())));
  34. LogInfo("Import done: " + pFileName);
  35. // Prepare widgets for new scene.
  36. ui->leFileName->setText(pFileName.right(pFileName.length() - pFileName.lastIndexOf('/') - 1));
  37. ui->lstLight->clear();
  38. ui->lstCamera->clear();
  39. ui->cbxLighting->setChecked(true), mGLView->Lighting_Enable();
  40. ui->cbxBBox->setChecked(false); mGLView->Enable_SceneBBox(false);
  41. ui->cbxTextures->setChecked(true), mGLView->Enable_Textures(true);
  42. //
  43. // Fill info labels
  44. //
  45. // Cameras
  46. ui->lblCameraCount->setText(QString("%1").arg(mScene->mNumCameras));
  47. // Lights
  48. ui->lblLightCount->setText(QString("%1").arg(mScene->mNumLights));
  49. // Meshes, faces, vertices.
  50. size_t qty_face = 0;
  51. size_t qty_vert = 0;
  52. for(size_t idx_mesh = 0; idx_mesh < mScene->mNumMeshes; idx_mesh++)
  53. {
  54. qty_face += mScene->mMeshes[idx_mesh]->mNumFaces;
  55. qty_vert += mScene->mMeshes[idx_mesh]->mNumVertices;
  56. }
  57. ui->lblMeshCount->setText(QString("%1").arg(mScene->mNumMeshes));
  58. ui->lblFaceCount->setText(QString("%1").arg(qty_face));
  59. ui->lblVertexCount->setText(QString("%1").arg(qty_vert));
  60. // Animation
  61. if(mScene->mNumAnimations)
  62. ui->lblHasAnimation->setText("yes");
  63. else
  64. ui->lblHasAnimation->setText("no");
  65. //
  66. // Set scene for GL viewer.
  67. //
  68. mGLView->SetScene(mScene, pFileName);
  69. // Select first camera
  70. ui->lstCamera->setCurrentRow(0);
  71. mGLView->Camera_Set(0);
  72. // Scene is loaded, do first rendering.
  73. LogInfo("Scene is ready for rendering.");
  74. mGLView->updateGL();
  75. }
  76. else
  77. {
  78. ui->lblLoadTime->clear();
  79. LogError(QString("Error parsing \'%1\' : \'%2\'").arg(pFileName).arg(mImporter.GetErrorString()));
  80. }// if(mScene != nullptr)
  81. }
  82. /********************************************************************/
  83. /************************ Logging functions *************************/
  84. /********************************************************************/
  85. void MainWindow::LogInfo(const QString& pMessage)
  86. {
  87. Assimp::DefaultLogger::get()->info(pMessage.toStdString());
  88. }
  89. void MainWindow::LogError(const QString& pMessage)
  90. {
  91. Assimp::DefaultLogger::get()->error(pMessage.toStdString());
  92. }
  93. /********************************************************************/
  94. /*********************** Overrided functions ************************/
  95. /********************************************************************/
  96. void MainWindow::mousePressEvent(QMouseEvent* pEvent)
  97. {
  98. if(pEvent->button() & Qt::LeftButton)
  99. mPosition_Pressed_LMB = pEvent->pos();
  100. else if(pEvent->button() & Qt::RightButton)
  101. mPosition_Pressed_RMB = pEvent->pos();
  102. }
  103. void MainWindow::mouseMoveEvent(QMouseEvent* pEvent)
  104. {
  105. if(pEvent->buttons() & Qt::LeftButton)
  106. {
  107. GLfloat dx = 180 * GLfloat(pEvent->x() - mPosition_Pressed_LMB.x()) / mGLView->width();
  108. GLfloat dy = 180 * GLfloat(pEvent->y() - mPosition_Pressed_LMB.y()) / mGLView->height();
  109. if(pEvent->modifiers() & Qt::ShiftModifier)
  110. mGLView->Camera_RotateScene(dy, 0, dx);// Rotate around oX and oZ axises.
  111. else
  112. mGLView->Camera_RotateScene(dy, dx, 0);// Rotate around oX and oY axises.
  113. mGLView->updateGL();
  114. mPosition_Pressed_LMB = pEvent->pos();
  115. }
  116. if(pEvent->buttons() & Qt::RightButton)
  117. {
  118. GLfloat dx = 180 * GLfloat(pEvent->x() - mPosition_Pressed_RMB.x()) / mGLView->width();
  119. GLfloat dy = 180 * GLfloat(pEvent->y() - mPosition_Pressed_RMB.y()) / mGLView->height();
  120. if(pEvent->modifiers() & Qt::ShiftModifier)
  121. mGLView->Camera_Rotate(dy, 0, dx);// Rotate around oX and oZ axises.
  122. else
  123. mGLView->Camera_Rotate(dy, dx, 0);// Rotate around oX and oY axises.
  124. mGLView->updateGL();
  125. mPosition_Pressed_RMB = pEvent->pos();
  126. }
  127. }
  128. void MainWindow::keyPressEvent(QKeyEvent* pEvent)
  129. {
  130. GLfloat step;
  131. if(pEvent->modifiers() & Qt::ControlModifier)
  132. step = 10;
  133. else if(pEvent->modifiers() & Qt::AltModifier)
  134. step = 100;
  135. else
  136. step = 1;
  137. if(pEvent->key() == Qt::Key_A)
  138. mGLView->Camera_Translate(-step, 0, 0);
  139. else if(pEvent->key() == Qt::Key_D)
  140. mGLView->Camera_Translate(step, 0, 0);
  141. else if(pEvent->key() == Qt::Key_W)
  142. mGLView->Camera_Translate(0, step, 0);
  143. else if(pEvent->key() == Qt::Key_S)
  144. mGLView->Camera_Translate(0, -step, 0);
  145. else if(pEvent->key() == Qt::Key_Up)
  146. mGLView->Camera_Translate(0, 0, -step);
  147. else if(pEvent->key() == Qt::Key_Down)
  148. mGLView->Camera_Translate(0, 0, step);
  149. mGLView->updateGL();
  150. }
  151. /********************************************************************/
  152. /********************** Constructor/Destructor **********************/
  153. /********************************************************************/
  154. MainWindow::MainWindow(QWidget *parent)
  155. : QMainWindow(parent), ui(new Ui::MainWindow),
  156. mScene(nullptr)
  157. {
  158. using namespace Assimp;
  159. ui->setupUi(this);
  160. // Create OpenGL widget
  161. mGLView = new CGLView(this);
  162. mGLView->setMinimumSize(800, 600);
  163. mGLView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
  164. mGLView->setFocusPolicy(Qt::StrongFocus);
  165. // Connect to GLView signals.
  166. connect(mGLView, SIGNAL(Paint_Finished(size_t, GLfloat)), SLOT(Paint_Finished(size_t, GLfloat)));
  167. connect(mGLView, SIGNAL(SceneObject_Camera(QString)), SLOT(SceneObject_Camera(QString)));
  168. connect(mGLView, SIGNAL(SceneObject_LightSource(QString)), SLOT(SceneObject_LightSource(QString)));
  169. // and add it to layout
  170. ui->hlMainView->insertWidget(0, mGLView, 4);
  171. // Create logger
  172. mLoggerView = new CLoggerView(ui->tbLog);
  173. DefaultLogger::create("", Logger::VERBOSE);
  174. DefaultLogger::get()->attachStream(mLoggerView, DefaultLogger::Debugging | DefaultLogger::Info | DefaultLogger::Err | DefaultLogger::Warn);
  175. }
  176. MainWindow::~MainWindow()
  177. {
  178. using namespace Assimp;
  179. DefaultLogger::get()->detatchStream(mLoggerView, DefaultLogger::Debugging | DefaultLogger::Info | DefaultLogger::Err | DefaultLogger::Warn);
  180. DefaultLogger::kill();
  181. if(mScene != nullptr) mImporter.FreeScene();
  182. if(mLoggerView != nullptr) delete mLoggerView;
  183. if(mGLView != nullptr) delete mGLView;
  184. delete ui;
  185. }
  186. /********************************************************************/
  187. /****************************** Slots *******************************/
  188. /********************************************************************/
  189. void MainWindow::Paint_Finished(const size_t pPaintTime_ms, const GLfloat pDistance)
  190. {
  191. ui->lblRenderTime->setText(QString("%1").arg(pPaintTime_ms));
  192. ui->lblDistance->setText(QString("%1").arg(pDistance));
  193. }
  194. void MainWindow::SceneObject_Camera(const QString& pName)
  195. {
  196. ui->lstCamera->addItem(pName);
  197. }
  198. void MainWindow::SceneObject_LightSource(const QString& pName)
  199. {
  200. ui->lstLight->addItem(pName);
  201. // After item added "currentRow" is still contain old value (even '-1' if first item added). Because "currentRow"/"currentItem" is changed by user interaction,
  202. // not by "addItem". So, "currentRow" must be set manually.
  203. ui->lstLight->setCurrentRow(ui->lstLight->count() - 1);
  204. // And after "selectAll" handler of "signal itemSelectionChanged" will get right "currentItem" and "currentRow" values.
  205. ui->lstLight->selectAll();
  206. }
  207. void MainWindow::on_butOpenFile_clicked()
  208. {
  209. aiString filter_temp;
  210. QString filename, filter;
  211. mImporter.GetExtensionList(filter_temp);
  212. filter = filter_temp.C_Str();
  213. filter.replace(';', ' ');
  214. filter.append(" ;; All (*.*)");
  215. filename = QFileDialog::getOpenFileName(this, "Choose the file", "", filter);
  216. if(!filename.isEmpty()) ImportFile(filename);
  217. }
  218. void MainWindow::on_butExport_clicked()
  219. {
  220. using namespace Assimp;
  221. QString filename, filter, format_id;
  222. Exporter exporter;
  223. QTime time_begin;
  224. aiReturn rv;
  225. if(mScene == nullptr)
  226. {
  227. QMessageBox::critical(this, "Export error", "Scene is empty");
  228. return;
  229. }
  230. // build filter
  231. {
  232. aiString filter_temp;
  233. mImporter.GetExtensionList(filter_temp);
  234. filter = filter_temp.C_Str();
  235. filter.replace(';', ' ');
  236. }
  237. // get file path
  238. filename = QFileDialog::getSaveFileName(this, "Set file name", "", filter);
  239. // extract format ID
  240. format_id = filename.right(filename.length() - filename.lastIndexOf('.') - 1);
  241. if(format_id.isEmpty())
  242. {
  243. QMessageBox::critical(this, "Export error", "File name must has extension.");
  244. return;
  245. }
  246. // begin export
  247. time_begin = QTime::currentTime();
  248. rv = exporter.Export(mScene, format_id.toLocal8Bit(), filename.toLocal8Bit());
  249. ui->lblExportTime->setText(QString("%1").arg(time_begin.secsTo(QTime::currentTime())));
  250. if(rv == aiReturn_SUCCESS)
  251. LogInfo("Export done: " + filename);
  252. else
  253. LogError("Export failed: " + filename);
  254. }
  255. void MainWindow::on_cbxLighting_clicked(bool pChecked)
  256. {
  257. if(pChecked)
  258. mGLView->Lighting_Enable();
  259. else
  260. mGLView->Lighting_Disable();
  261. mGLView->updateGL();
  262. }
  263. void MainWindow::on_lstLight_itemSelectionChanged()
  264. {
  265. bool selected = ui->lstLight->isItemSelected(ui->lstLight->currentItem());
  266. if(selected)
  267. mGLView->Lighting_EnableSource(ui->lstLight->currentRow());
  268. else
  269. mGLView->Lighting_DisableSource(ui->lstLight->currentRow());
  270. mGLView->updateGL();
  271. }
  272. void MainWindow::on_lstCamera_clicked( const QModelIndex &)
  273. {
  274. mGLView->Camera_Set(ui->lstLight->currentRow());
  275. mGLView->updateGL();
  276. }
  277. void MainWindow::on_cbxBBox_clicked(bool checked)
  278. {
  279. mGLView->Enable_SceneBBox(checked);
  280. mGLView->updateGL();
  281. }
  282. void MainWindow::on_cbxTextures_clicked(bool checked)
  283. {
  284. mGLView->Enable_Textures(checked);
  285. mGLView->updateGL();
  286. }