/** * atom dynamics * @author Tobias Weber * @date Dec-2019 * @license GPLv3, see 'LICENSE' file */ #include "moldyn.h" #include #include #include #include #include #include #include "libs/algos.h" #include "libs/helper.h" using namespace m_ops; constexpr t_real g_eps = 1e-6; constexpr int g_prec = 6; // ---------------------------------------------------------------------------- MolDynDlg::MolDynDlg(QWidget* pParent) : QMainWindow{pParent}, m_sett{new QSettings{"tobis_stuff", "moldyn"}} { setWindowTitle("Molecular Dynamics"); this->setObjectName("moldyn"); m_status = new QStatusBar(this); this->setStatusBar(m_status); QWidget *pMainPanel = new QWidget(); auto pMainGrid = new QGridLayout(pMainPanel); pMainGrid->setSpacing(2); pMainGrid->setContentsMargins(4,4,4,4); this->setCentralWidget(pMainPanel); // menu bar { m_menu = new QMenuBar(this); m_menu->setNativeMenuBar(m_sett ? m_sett->value("native_gui", false).toBool() : false); auto menuFile = new QMenu("File", m_menu); auto acNew = new QAction("New", menuFile); auto acLoad = new QAction("Load...", menuFile); //auto acSave = new QAction("Save...", menuFile); auto acExit = new QAction("Exit", menuFile); menuFile->addAction(acNew); menuFile->addSeparator(); menuFile->addAction(acLoad); //menuFile->addAction(acSave); menuFile->addSeparator(); menuFile->addAction(acExit); connect(acNew, &QAction::triggered, this, &MolDynDlg::New); connect(acLoad, &QAction::triggered, this, &MolDynDlg::Load); //connect(acSave, &QAction::triggered, this, &MolDynDlg::Save); connect(acExit, &QAction::triggered, this, &QDialog::close); m_menu->addMenu(menuFile); this->setMenuBar(m_menu); } // plot widget { m_plot = new GlPlot(this); m_plot->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Expanding}); m_plot->GetImpl()->EnablePicker(1); m_plot->GetImpl()->SetLight(0, m::create({ 5, 5, 5 })); m_plot->GetImpl()->SetLight(1, m::create({ -5, -5, -5 })); m_plot->GetImpl()->SetCoordMax(1.); m_plot->GetImpl()->SetCamBase(m::create({1,0,0,0, 0,0,1,0, 0,-1,0,-1.5, 0,0,0,1}), m::create({1,0,0,0}), m::create({0,0,1,0})); connect(m_plot, &GlPlot::AfterGLInitialisation, this, &MolDynDlg::AfterGLInitialisation); connect(m_plot->GetImpl(), &GlPlot_impl::PickerIntersection, this, &MolDynDlg::PickerIntersection); connect(m_plot, &GlPlot::MouseDown, this, &MolDynDlg::PlotMouseDown); connect(m_plot, &GlPlot::MouseUp, this, &MolDynDlg::PlotMouseUp); //this->setCentralWidget(m_plot); pMainGrid->addWidget(m_plot, 0,0,1,1); } // controls { m_slider = new QSlider(Qt::Horizontal, this); m_slider->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Minimum}); m_slider->setMinimum(0); m_slider->setTracking(1); connect(m_slider, &QSlider::valueChanged, this, &MolDynDlg::SliderValueChanged); pMainGrid->addWidget(m_slider, 1,0,1,1); } // restore window size and position if(m_sett && m_sett->contains("geo")) restoreGeometry(m_sett->value("geo").toByteArray()); else resize(600, 500); m_ignoreChanges = 0; } // ---------------------------------------------------------------------------- /** * add 3d object */ std::size_t MolDynDlg::Add3DItem(const t_vec& vec, const t_vec& col, t_real scale, const std::string& label) { auto obj = m_plot->GetImpl()->AddLinkedObject(m_sphere, 0,0,0, col[0],col[1],col[2],1); //auto obj = m_plot->GetImpl()->AddSphere(0.05, 0,0,0, col[0],col[1],col[2],1); m_plot->GetImpl()->SetObjectMatrix(obj, m::hom_translation(vec[0], vec[1], vec[2])*m::hom_scaling(scale,scale,scale)); m_plot->GetImpl()->SetObjectLabel(obj, label); m_plot->GetImpl()->SetObjectDataString(obj, label); m_plot->update(); return obj; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- void MolDynDlg::New() { m_mol.Clear(); m_sphereHandles.clear(); // TODO: clear 3d objects } void MolDynDlg::Load() { if(!m_plot) return; m_ignoreCalc = 1; try { QString dirLast = m_sett->value("dir", "").toString(); QString filename = QFileDialog::getOpenFileName(this, "Load File", dirLast, "Molecular Dynamics File (*)"); if(filename=="" || !QFile::exists(filename)) return; m_sett->setValue("dir", QFileInfo(filename).path()); unsigned int frameskip = 10; if(!m_mol.LoadFile(filename.toStdString(), frameskip)) { QMessageBox::critical(this, "Molecular Dynamics", "Error loading file."); return; } m_slider->setMaximum(m_mol.GetFrameCount()); // atom colors std::vector cols = { m::create({1, 0, 0}), m::create({0, 0, 1}), m::create({0, 0.5, 0}), m::create({0, 0.5, 0.5}), m::create({0.5, 0.5, 0}), m::create({0, 0, 0}), }; // add atoms to 3d view if(m_mol.GetFrameCount()) { const auto& frame = m_mol.GetFrame(0); m_sphereHandles.reserve(frame.GetNumAtoms()); for(std::size_t atomidx=0; atomidx 0) { const std::string& label = m_plot->GetImpl()->GetObjectDataString(m_curPickedObj); SetStatusMsg(label); } else { SetStatusMsg(""); } } /** * set status label text in 3d dialog */ void MolDynDlg::SetStatusMsg(const std::string& msg) { if(!m_status) return; m_status->showMessage(msg.c_str()); } /** * mouse button pressed */ void MolDynDlg::PlotMouseDown(bool left, bool mid, bool right) { if(left && m_curPickedObj > 0) { } } /** * mouse button released */ void MolDynDlg::PlotMouseUp(bool left, bool mid, bool right) { } // ---------------------------------------------------------------------------- void MolDynDlg::SliderValueChanged(int val) { if(!m_plot) return; if(val < 0 || val >= m_mol.GetFrameCount()) return; // update atom position with selected frame const auto& frame = m_mol.GetFrame(val); std::size_t counter = 0; for(std::size_t atomidx=0; atomidxGetImpl()->SetObjectMatrix(obj, m::hom_translation(vec[0], vec[1], vec[2])*m::hom_scaling(scale,scale,scale)); ++counter; } } m_plot->update(); } // ---------------------------------------------------------------------------- void MolDynDlg::AfterGLInitialisation() { if(!m_plot) return; // reference sphere for linked objects m_sphere = m_plot->GetImpl()->AddSphere(0.05, 0.,0.,0., 1.,1.,1.,1.); m_plot->GetImpl()->SetObjectVisible(m_sphere, false); // GL device info auto [strGlVer, strGlShaderVer, strGlVendor, strGlRenderer] = m_plot->GetImpl()->GetGlDescr(); std::cout << "GL Version: " << strGlVer << ", Shader Version: " << strGlShaderVer << "." << std::endl; std::cout << "GL Device: " << strGlRenderer << ", " << strGlVendor << "." << std::endl; } void MolDynDlg::closeEvent(QCloseEvent *evt) { if(m_sett) { m_sett->setValue("geo", saveGeometry()); } } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- int main(int argc, char** argv) { set_gl_format(1, _GL_MAJ_VER, _GL_MIN_VER, 8); tl2::set_locales(); auto app = std::make_unique(argc, argv); auto dlg = std::make_unique(nullptr); dlg->show(); return app->exec(); } // ----------------------------------------------------------------------------