source: src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.cpp@ 6c4b69

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 6c4b69 was 691533, checked in by Frederik Heber <heber@…>, 9 years ago

FIX: GLMoleculeObject_molecule only updates tesselation hull when necessary.

  • Property mode set to 100644
File size: 11.1 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
6 *
7 *
8 * This file is part of MoleCuilder.
9 *
10 * MoleCuilder is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * MoleCuilder is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24/*
25 * GLMoleculeObject_molecule.cpp
26 *
27 * Created on: Mar 30, 2012
28 * Author: ankele
29 */
30
31
32// include config.h
33#ifdef HAVE_CONFIG_H
34#include <config.h>
35#endif
36
37#include "GLMoleculeObject_molecule.hpp"
38
39#include <Qt3D/qglscenenode.h>
40#include <Qt3D/qglbuilder.h>
41
42#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_atom.hpp"
43
44#include "CodePatterns/MemDebug.hpp"
45
46#include "CodePatterns/Assert.hpp"
47#include "CodePatterns/IteratorAdaptors.hpp"
48#include "CodePatterns/Log.hpp"
49
50#include "LinearAlgebra/Vector.hpp"
51#include "LinkedCell/PointCloudAdaptor.hpp"
52#include "LinkedCell/linkedcell.hpp"
53#include "Tesselation/tesselation.hpp"
54#include "Tesselation/BoundaryLineSet.hpp"
55#include "Tesselation/BoundaryTriangleSet.hpp"
56#include "Tesselation/CandidateForTesselation.hpp"
57#include "UIElements/Qt4/InstanceBoard/QtObservedInstanceBoard.hpp"
58#include "Atom/TesselPoint.hpp"
59#include "World.hpp"
60
61static QGLSceneNode *createMoleculeMesh(const QGeometryData &_geo)
62{
63 // Build a mesh from the geometry.
64 QGLBuilder builder;
65 builder.addTriangles(_geo);
66 QGLSceneNode *mesh = builder.finalizedSceneNode();
67 return mesh;
68}
69
70GLMoleculeObject_molecule::GLMoleculeObject_molecule(
71 QObject *parent,
72 QtObservedMolecule::ptr &_ObservedMolecule) :
73 GLMoleculeObject((QGLSceneNode *)NULL, parent),
74 hoverAtomId(-1),
75 ObservedMolecule(_ObservedMolecule)
76{
77 init();
78}
79
80GLMoleculeObject_molecule::GLMoleculeObject_molecule(
81 QGLSceneNode *mesh[],
82 QObject *parent,
83 QtObservedMolecule::ptr &_ObservedMolecule) :
84 GLMoleculeObject(mesh, parent),
85 TesselationUptodate(false),
86 hoverAtomId(-1),
87 ObservedMolecule(_ObservedMolecule)
88{
89 init();
90}
91
92void GLMoleculeObject_molecule::init()
93{
94 setObjectId(ObservedMolecule->getMolIndex());
95 setMaterial(getMaterial(1));
96
97 m_selected = ObservedMolecule->getMolSelected();
98
99 // initially, atoms and bonds should be visible
100 m_visible = false;
101
102 connect (ObservedMolecule.get(), SIGNAL(tesselationhullChanged()), this, SLOT(setTesselationOutOfDate()));
103 connect (ObservedMolecule.get(), SIGNAL(boundingboxChanged()), this, SLOT(resetBoundingBox()));
104 connect (ObservedMolecule.get(), SIGNAL(indexChanged(const moleculeId_t, const moleculeId_t)),
105 this, SLOT(resetIndex(const moleculeId_t, const moleculeId_t)));
106 /// these are channeled through GLWorldScene instead to ensure synchronicity
107// connect (ObservedMolecule.get(), SIGNAL(atomInserted(QtObservedAtom::ptr)),
108// this, SLOT(atomInserted(QtObservedAtom::ptr)) );
109// connect (ObservedMolecule.get(), SIGNAL(atomRemoved(const atomId_t)),
110// this, SLOT(atomRemoved(const atomId_t)) );
111 connect (ObservedMolecule.get(), SIGNAL(selectedChanged()), this, SLOT(resetSelected()));
112}
113
114GLMoleculeObject_molecule::~GLMoleculeObject_molecule()
115{}
116
117QGeometryData GLMoleculeObject_molecule::updateTesselationHull() const
118{
119 QGeometryData geo;
120
121 const molecule * const molref =
122 QtObservedMolecule::getMolecule(ObservedMolecule->getMolIndex());
123 if (molref == NULL) {
124 ELOG(1, "Could not createMoleculeMesh, molecule with id "
125 << ObservedMolecule->getMolIndex() << " already gone.");
126 return geo;
127 }
128 double minradius = 2.; // TODO: set to maximum bond length value
129 LOG(3, "DEBUG: Molecule fits into sphere of radius " << minradius);
130 // check minimum bond radius in molecule
131 double minlength = std::numeric_limits<double>::max();
132 size_t NoAtoms = 0;
133 for (molecule::const_iterator iter = molref->begin();
134 iter != molref->end(); ++iter) {
135 const BondList &ListOfBonds = (*iter)->getListOfBonds();
136 for (BondList::const_iterator bonditer = ListOfBonds.begin();
137 bonditer != ListOfBonds.end(); ++bonditer) {
138 const double bond_distance = (*bonditer)->GetDistance();
139 minlength = std::min(bond_distance, minlength);
140 }
141 ++NoAtoms;
142 }
143 minradius = std::max( std::max(minradius, minlength), 1.);
144
145 // we need at least three points for tesselation
146 if (NoAtoms >= 3) {
147 // Tesselate the points.
148 Tesselation T;
149 PointCloudAdaptor<molecule> cloud(
150 const_cast<molecule *>(molref),
151 ObservedMolecule->getMolName());
152 T(cloud, minradius);
153
154 // Fill the points into a Qt geometry.
155 LinkedCell_deprecated LinkedList(cloud, minradius);
156 std::map<int, int> indices;
157 std::map<int, Vector> normals;
158 int index = 0;
159 for (PointMap::const_iterator piter = T.PointsOnBoundary.begin();
160 piter != T.PointsOnBoundary.end(); ++piter) {
161 const Vector &point = piter->second->getPosition();
162 // add data to the primitive
163 geo.appendVertex(QVector3D(point[0], point[1], point[2]));
164 Vector normalvector;
165 for (LineMap::const_iterator lineiter = piter->second->lines.begin();
166 lineiter != piter->second->lines.end(); ++lineiter)
167 for (TriangleMap::const_iterator triangleiter = lineiter->second->triangles.begin();
168 triangleiter != lineiter->second->triangles.end(); ++triangleiter)
169 normalvector +=
170 triangleiter->second->NormalVector;
171 normalvector.Normalize();
172 geo.appendNormal(QVector3D(normalvector[0], normalvector[1], normalvector[2]));
173 geo.appendColor(QColor(1, 1, 1, 1));
174 geo.appendTexCoord(QVector2D(0, 0));
175 indices.insert( std::make_pair( piter->second->getNr(), index++));
176 }
177
178 // Fill the tesselated triangles into the geometry.
179 for (TriangleMap::const_iterator runner = T.TrianglesOnBoundary.begin();
180 runner != T.TrianglesOnBoundary.end(); runner++) {
181 int v[3];
182 for (size_t i=0; i<3; ++i)
183 v[i] = runner->second->endpoints[i]->getNr();
184
185 // Sort the vertices so the triangle is clockwise (relative to the normal vector).
186 Vector cross = T.PointsOnBoundary[v[1]]->getPosition() - T.PointsOnBoundary[v[0]]->getPosition();
187 cross.VectorProduct(T.PointsOnBoundary[v[2]]->getPosition() - T.PointsOnBoundary[v[0]]->getPosition());
188 if (cross.ScalarProduct(runner->second->NormalVector) > 0)
189 geo.appendIndices(indices[v[0]], indices[v[1]], indices[v[2]]);
190 else
191 geo.appendIndices(indices[v[0]], indices[v[2]], indices[v[1]]);
192 }
193 }
194
195 return geo;
196}
197
198void GLMoleculeObject_molecule::setTesselationOutOfDate()
199{
200 TesselationUptodate = false;
201}
202
203void GLMoleculeObject_molecule::resetTesselationHull()
204{
205 if (!TesselationUptodate) {
206 TesselationHull = updateTesselationHull();
207 updateMesh(createMoleculeMesh(TesselationHull));
208 TesselationUptodate = true;
209 }
210}
211
212void GLMoleculeObject_molecule::resetBoundingBox()
213{
214 molecule::BoundingBoxInfo info = ObservedMolecule->getBoundingBox();
215 setPosition(QVector3D(info.position[0], info.position[1], info.position[2]));
216 setScale(info.radius + 0.3); // getBoundingSphere() only sees atoms as points, so make the box a bit bigger
217}
218
219void GLMoleculeObject_molecule::resetIndex(const moleculeId_t, const moleculeId_t)
220{
221 const atomId_t newId = ObservedMolecule->getMolIndex();
222 const size_t oldId = objectId();
223 ASSERT( newId != oldId,
224 "GLMoleculeObject_molecule::resetIndex() - index "+toString(newId)+" did not change.");
225 LOG(4, "INFO: GLMoleculeObject_molecule: new index is "+toString(newId)+".");
226 setObjectId(newId);
227}
228
229void GLMoleculeObject_molecule::resetSelected()
230{
231 const bool new_selected = ObservedMolecule->getMolSelected();
232 m_selected = new_selected;
233
234 emit changed();
235}
236
237void GLMoleculeObject_molecule::initialize(QGLView *view, QGLPainter *painter)
238{
239 // Initialize all of the mesh objects that we have as children.
240 if (m_visible) {
241 GLMoleculeObject::initialize(view, painter);
242 } else {
243 foreach (QObject *obj, children()) {
244 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
245 if (meshobj)
246 meshobj->initialize(view, painter);
247 }
248 }
249}
250
251void GLMoleculeObject_molecule::draw(QGLPainter *painter, const QVector4D &cameraPlane)
252{
253 // draw either molecule's mesh or all atoms and bonds
254 if (m_visible) {
255 resetTesselationHull();
256
257 painter->modelViewMatrix().push();
258
259 // Apply the material and effect to the painter.
260 QGLMaterial *material;
261 if (m_hovering)
262 material = m_hoverMaterial;
263 else if (m_selected)
264 material = m_selectionMaterial;
265 else
266 material = m_material;
267
268 ASSERT(material, "GLMoleculeObject::draw: chosen material is NULL");
269
270 painter->setColor(material->diffuseColor());
271 painter->setFaceMaterial(QGL::AllFaces, material);
272 if (m_effect)
273 painter->setUserEffect(m_effect);
274 else
275 painter->setStandardEffect(QGL::LitMaterial);
276
277 // Mark the object for object picking purposes.
278 int prevObjectId = painter->objectPickId();
279 if (m_objectId != -1)
280 painter->setObjectPickId(m_objectId);
281
282 m_mesh[0]->draw(painter);
283
284 // Turn off the user effect, if present.
285 if (m_effect)
286 painter->setStandardEffect(QGL::LitMaterial);
287
288 // Revert to the previous object identifier.
289 painter->setObjectPickId(prevObjectId);
290
291 // Restore the modelview matrix.
292 painter->modelViewMatrix().pop();
293
294 // GLMoleculeObject::draw(painter, cameraPlane);
295 } else {
296 // Draw all of the mesh objects that we have as children.
297 foreach (QObject *obj, children()) {
298 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
299 if (meshobj)
300 meshobj->draw(painter, cameraPlane);
301 }
302
303 // update bounding box prior to selection
304 resetBoundingBox();
305
306 painter->modelViewMatrix().push();
307 painter->modelViewMatrix().translate(m_position);
308 if (m_rotationAngle != 0.0f)
309 painter->modelViewMatrix().rotate(m_rotationAngle, m_rotationVector);
310 if ((m_scaleX != 1.0f) || (m_scaleY != 1.0f) || (m_scaleZ != 1.0f))
311 painter->modelViewMatrix().scale(m_scaleX, m_scaleY, m_scaleZ);
312
313 // Draw a box around the mesh, if selected.
314 if (m_selected)
315 drawSelectionBox(painter);
316
317 // Restore the modelview matrix.
318 painter->modelViewMatrix().pop();
319 }
320}
321
322void GLMoleculeObject_molecule::setVisible(bool value)
323{
324 // first update the mesh if we are going to be visible now
325 if (value)
326 updateTesselationHull();
327 // then emit onward
328 GLMoleculeObject::setVisible(value);
329
330 emit changed();
331 emit changeOccured();
332}
333
334std::ostream &operator<<(std::ostream &ost, const GLMoleculeObject_molecule::BondIds &t)
335{
336 ost << t.first << "," << t.second;
337 return ost;
338}
Note: See TracBrowser for help on using the repository browser.