source: src/UIElements/Views/Qt4/Qt3D/GLWorldView.cpp@ 708277

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 708277 was 708277, checked in by Frederik Heber <heber@…>, 12 years ago

FIX: Using fixed Observer in CodePatterns 1.2.6.

  • we now require CodePatterns 1.2.6.
  • Notifications now use subjectKilled() when the Observable they are associated with is destroyed. This allows Observers that are just sign on to a single channel safely sign off.
  • also, derived Observable classes must not remove their Channels and Notifications by themselves. This is done by the Observable base class. Otherwise, subjectKilled() is not called.
  • changed AtomObserver: Is directly connected to the atom class, AtomInserted and AtomRemoved called in its cstor and dstor. The World has nothing to do with it. However, we have to make sure AtomObserver is purged after World.
  • Fixed also some faulty uses of ObserverLog and we always insert into NotificationChannels with static_cast to Observable for clarity.
  • Property mode set to 100644
File size: 57.9 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 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * GLWorldView.cpp
25 *
26 * Created on: Aug 1, 2010
27 * Author: heber
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35#include "GLWorldView.hpp"
36
37#include <Qt/qevent.h>
38#include <Qt/qaction.h>
39#include <QtGui/QMenu>
40#include <QtGui/QToolBar>
41#include <QtGui/QToolButton>
42#include <Qt/qtimer.h>
43#include <Qt/qsettings.h>
44#include <Qt3D/qglbuilder.h>
45#include <Qt3D/qglscenenode.h>
46#include <Qt3D/qglsphere.h>
47#include <Qt3D/qglcylinder.h>
48#include <Qt3D/qglcube.h>
49
50#include "GLWorldScene.hpp"
51
52#include "CodePatterns/MemDebug.hpp"
53
54#include "Atom/AtomObserver.hpp"
55#include "Atom/atom_observable.hpp"
56#include "Box.hpp"
57#include "CodePatterns/Log.hpp"
58#include "CodePatterns/Observer/Notification.hpp"
59#include "CodePatterns/Observer/ObserverLog.hpp"
60#include "molecule.hpp"
61#include "Shapes/ShapeRegistry.hpp"
62#include "World.hpp"
63
64GLWorldView::GLWorldView(QWidget *parent)
65 : QGLView(parent), Observer("GLWorldView"), worldscene(NULL), changesPresent(false), needsRedraw(false)
66{
67 worldscene = new GLWorldScene(this);
68
69 setOption(QGLView::ObjectPicking, true);
70 setOption(QGLView::CameraNavigation, false);
71 setCameraControlMode(Rotate);
72 defaultEyeSeparation = 4.0;
73
74 createDomainBox();
75 createDreiBein();
76 //changeMaterials(false);
77
78 connect(worldscene, SIGNAL(changeOccured()), this, SLOT(changeSignalled()));
79 connect(worldscene, SIGNAL(changed()), this, SIGNAL(changed()));
80 connect(worldscene, SIGNAL(hoverChanged(const atom *)), this, SLOT(sceneHoverSignalled(const atom *)));
81 connect(this, SIGNAL(atomInserted(const atom *)), worldscene, SLOT(atomInserted(const atom *)));
82 connect(this, SIGNAL(atomRemoved(const atom *)), worldscene, SLOT(atomRemoved(const atom *)));
83 connect(this, SIGNAL(worldSelectionChanged()), worldscene, SLOT(worldSelectionChanged()));
84 connect(this, SIGNAL(moleculeRemoved(const molecule *)), worldscene, SLOT(moleculeRemoved(const molecule *)));
85 //connect(this, SIGNAL(moleculeInserted(const molecule *)), worldscene, SLOT(moleculeInserted(const molecule *)));
86 //connect(this, SIGNAL(changed()), this, SLOT(updateGL()));
87 connect(this, SIGNAL(changed()), this, SLOT(sceneChangeSignalled()));
88
89 // sign on to changes in the world
90 World::getInstance().signOn(this);
91 World::getInstance().signOn(this, World::AtomInserted);
92 World::getInstance().signOn(this, World::AtomRemoved);
93 World::getInstance().signOn(this, World::MoleculeInserted);
94 World::getInstance().signOn(this, World::MoleculeRemoved);
95 World::getInstance().signOn(this, World::SelectionChanged);
96 AtomObserver::getInstance().signOn(this, AtomObservable::PositionChanged);
97
98 ShapeRegistry::getInstance().signOn(this);
99 ShapeRegistry::getInstance().signOn(this, ShapeRegistry::ShapeInserted);
100 ShapeRegistry::getInstance().signOn(this, ShapeRegistry::ShapeRemoved);
101 ShapeRegistry::getInstance().signOn(this, ShapeRegistry::SelectionChanged);
102
103 redrawTimer = new QTimer(this);
104}
105
106GLWorldView::~GLWorldView()
107{
108 World::getInstance().signOff(this);
109 World::getInstance().signOff(this, World::AtomInserted);
110 World::getInstance().signOff(this, World::AtomRemoved);
111 World::getInstance().signOff(this, World::MoleculeInserted);
112 World::getInstance().signOff(this, World::MoleculeRemoved);
113 World::getInstance().signOff(this, World::SelectionChanged);
114 AtomObserver::getInstance().signOff(this, AtomObservable::PositionChanged);
115 ShapeRegistry::getInstance().signOff(this);
116 ShapeRegistry::getInstance().signOff(this, ShapeRegistry::ShapeInserted);
117 ShapeRegistry::getInstance().signOff(this, ShapeRegistry::ShapeRemoved);
118 ShapeRegistry::getInstance().signOff(this, ShapeRegistry::SelectionChanged);
119 delete worldscene;
120
121 delete(domainBoxMaterial);
122 for (int i=0;i<3;i++)
123 delete(dreiBeinMaterial[i]);
124}
125
126
127/**
128 * Add some widget specific actions to the toolbar:
129 * - camera rotation/translation mode
130 * - camera fit to domain
131 */
132void GLWorldView::addToolBarActions(QToolBar *toolbar)
133{
134 // camera control mode
135 toolbar->addSeparator();
136 QAction *transAction = new QAction(QIcon::fromTheme("forward"), tr("camera translation mode"), this);
137 connect(transAction, SIGNAL(triggered()), this, SLOT(setCameraControlModeTranslation()));
138 toolbar->addAction(transAction);
139 QAction *rotAction = new QAction(QIcon::fromTheme("object-rotate-left"), tr("camera rotation mode"), this);
140 connect(rotAction, SIGNAL(triggered()), this, SLOT(setCameraControlModeRotation()));
141 toolbar->addAction(rotAction);
142 QAction *fitAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("camera fit to domain"), this);
143 connect(fitAction, SIGNAL(triggered()), this, SLOT(fitCameraToDomain()));
144 toolbar->addAction(fitAction);
145
146 // stereo mode
147 QToolButton *stereoButton = new QToolButton(toolbar);
148 QMenu *stereoMenu = new QMenu();
149 QAction *stereoDisableAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("disable"), this);
150 connect(stereoDisableAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeDisable()));
151 stereoMenu->addAction(stereoDisableAction);
152 QAction *stereoHardwareAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("hardware"), this);
153 connect(stereoHardwareAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeHardware()));
154 stereoMenu->addAction(stereoHardwareAction);
155 QAction *stereoLeftRightAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("left right"), this);
156 connect(stereoLeftRightAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeLeftRight()));
157 stereoMenu->addAction(stereoLeftRightAction);
158 QAction *stereoRightLeftAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("right left"), this);
159 connect(stereoRightLeftAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeRightLeft()));
160 stereoMenu->addAction(stereoRightLeftAction);
161 QAction *stereoTopBottomAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("top bottom"), this);
162 connect(stereoTopBottomAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeTopBottom()));
163 stereoMenu->addAction(stereoTopBottomAction);
164 QAction *stereoBottomTopAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("bottom top"), this);
165 connect(stereoBottomTopAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeBottomTop()));
166 stereoMenu->addAction(stereoBottomTopAction);
167 QAction *stereoAnaglyphAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("anaglyph"), this);
168 connect(stereoAnaglyphAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeAnaglyph()));
169 stereoMenu->addAction(stereoAnaglyphAction);
170 stereoButton->setMenu(stereoMenu);
171 stereoButton->setIcon(QIcon(QPixmap(":/icon_view_stereo.png")));
172 stereoButton->setPopupMode(QToolButton::InstantPopup);
173 toolbar->addWidget(stereoButton);
174
175 // selection mode
176 toolbar->addSeparator();
177 QAction *selAtomAction = new QAction(QIcon(QPixmap(":/icon_select_atom.png")), tr("select atom by clicking"), this);
178 connect(selAtomAction, SIGNAL(triggered()), worldscene, SLOT(setSelectionModeAtom()));
179 toolbar->addAction(selAtomAction);
180 QAction *selMolAction = new QAction(QIcon(QPixmap(":/icon_select_molecule.png")), tr("select molecule by clicking"), this);
181 connect(selMolAction, SIGNAL(triggered()), worldscene, SLOT(setSelectionModeMolecule()));
182 toolbar->addAction(selMolAction);
183}
184
185void GLWorldView::createDomainBox()
186{
187 QSettings settings;
188 settings.beginGroup("WorldView");
189 QColor colorFrame = settings.value("domainBoxColorFrame", QColor(150,160,200,255)).value<QColor>();
190 QColor colorAmbient = settings.value("domainBoxColorAmbient", QColor(50,60,100,255)).value<QColor>();
191 QColor colorDiffuse = settings.value("domainBoxColorDiffuse", QColor(150,160,200,180)).value<QColor>();
192 settings.setValue("domainBoxColorFrame", colorFrame);
193 settings.setValue("domainBoxColorAmbient", colorAmbient);
194 settings.setValue("domainBoxColorDiffuse", colorDiffuse);
195 settings.endGroup();
196
197 domainBoxMaterial = new QGLMaterial;
198 domainBoxMaterial->setAmbientColor(QColor(0,0,0,255));
199 domainBoxMaterial->setDiffuseColor(QColor(0,0,0,255));
200 domainBoxMaterial->setEmittedLight(colorFrame);
201
202
203 QGLMaterial *material = new QGLMaterial;
204 material->setAmbientColor(colorAmbient);
205 material->setDiffuseColor(colorDiffuse);
206
207 QGLBuilder builder;
208 builder << QGL::Faceted;
209 builder << QGLCube(-1.0); // "inverted" => inside faces are used as front.
210 meshDomainBox = builder.finalizedSceneNode();
211 QMatrix4x4 mat;
212 mat.translate(0.5f, 0.5f, 0.5f);
213 meshDomainBox->setLocalTransform(mat);
214 meshDomainBox->setMaterial(material);
215}
216
217void GLWorldView::createDreiBein()
218{
219 QSettings settings;
220 settings.beginGroup("WorldView");
221 QColor colorX = settings.value("dreiBeinColorX", QColor(255,50,50,255)).value<QColor>();
222 QColor colorY = settings.value("dreiBeinColorY", QColor(50,255,50,255)).value<QColor>();
223 QColor colorZ = settings.value("dreiBeinColorZ", QColor(50,50,255,255)).value<QColor>();
224 settings.setValue("dreiBeinColorX", colorX);
225 settings.setValue("dreiBeinColorY", colorY);
226 settings.setValue("dreiBeinColorZ", colorZ);
227 settings.setValue("dreiBeinEnabled", true);
228 settings.endGroup();
229
230 // Create 3 color for the 3 axes.
231 dreiBeinMaterial[0] = new QGLMaterial;
232 dreiBeinMaterial[0]->setColor(colorX);
233 dreiBeinMaterial[1] = new QGLMaterial;
234 dreiBeinMaterial[1]->setColor(colorY);
235 dreiBeinMaterial[2] = new QGLMaterial;
236 dreiBeinMaterial[2]->setColor(colorZ);
237
238 // Create the basic meshes (cylinder and cone).
239 QGLBuilder builderCyl;
240 builderCyl << QGLCylinder(.15,.15,1.6,16);
241 QGLSceneNode *cyl = builderCyl.finalizedSceneNode();
242
243 QGLBuilder builderCone;
244 builderCone << QGLCylinder(0,.4,0.4,16);
245 QGLSceneNode *cone = builderCone.finalizedSceneNode();
246 {
247 QMatrix4x4 mat;
248 mat.translate(0.0f, 0.0f, 1.0f);
249 cone->setLocalTransform(mat);
250 }
251
252 // Create a scene node from the 3 axes.
253 meshDreiBein = new QGLSceneNode(this);
254
255 // X-direction
256 QGLSceneNode *node = new QGLSceneNode(meshDreiBein);
257 node->setMaterial(dreiBeinMaterial[0]);
258 node->addNode(cyl);
259 node->setPosition(QVector3D(.8f, 0.f, 0.f));
260 node->addNode(cone);
261 {
262 QMatrix4x4 mat;
263 mat.rotate(90, 0.0f, 1.0f, 0.0f);
264 node->setLocalTransform(mat);
265 }
266
267 // Y-direction
268 node = new QGLSceneNode(meshDreiBein);
269 node->setMaterial(dreiBeinMaterial[1]);
270 node->addNode(cyl);
271 node->addNode(cone);
272 {
273 QMatrix4x4 mat;
274 mat.rotate(-90, 1.0f, 0.0f, 0.0f);
275 node->setLocalTransform(mat);
276 }
277 node->setPosition(QVector3D(0.f, .8f, 0.f));
278
279 // Z-direction
280 node = new QGLSceneNode(meshDreiBein);
281 node->setMaterial(dreiBeinMaterial[2]);
282 node->addNode(cyl);
283 node->addNode(cone);
284 node->setPosition(QVector3D(0.f, 0.f, .8f));
285}
286
287/**
288 * Update operation which can be invoked by the observable (which should be the
289 * change tracker here).
290 */
291void GLWorldView::update(Observable *publisher)
292{
293 emit changed();
294}
295
296/**
297 * The observable can tell when it dies.
298 */
299void GLWorldView::subjectKilled(Observable *publisher) {}
300
301/** Listen to specific changes to the world.
302 *
303 * @param publisher ref to observable.
304 * @param notification type of notification
305 */
306void GLWorldView::recieveNotification(Observable *publisher, Notification_ptr notification)
307{
308 if (static_cast<World *>(publisher) == World::getPointer()) {
309 switch (notification->getChannelNo()) {
310 case World::AtomInserted:
311 {
312 const atom *_atom = World::getInstance().lastChanged<atom>();
313 #ifdef LOG_OBSERVER
314 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_atom->getId())+" has been inserted.";
315 #endif
316 emit atomInserted(_atom);
317 break;
318 }
319 case World::AtomRemoved:
320 {
321 const atom *_atom = World::getInstance().lastChanged<atom>();
322 #ifdef LOG_OBSERVER
323 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_atom->getId())+" has been removed.";
324 #endif
325 emit atomRemoved(_atom);
326 break;
327 }
328 case World::SelectionChanged:
329 {
330 #ifdef LOG_OBSERVER
331 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that selection has changed.";
332 #endif
333 emit worldSelectionChanged();
334 break;
335 }
336 case World::MoleculeInserted:
337 {
338 const molecule *_molecule = World::getInstance().lastChanged<molecule>();
339 #ifdef LOG_OBSERVER
340 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that molecule "+toString(_molecule->getId())+" has been removed.";
341 #endif
342 emit moleculeInserted(_molecule);
343 break;
344 }
345 case World::MoleculeRemoved:
346 {
347 const molecule *_molecule = World::getInstance().lastChanged<molecule>();
348 #ifdef LOG_OBSERVER
349 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that molecule "+toString(_molecule->getId())+" has been removed.";
350 #endif
351 emit moleculeRemoved(_molecule);
352 break;
353 }
354 default:
355 ASSERT(0, "GLWorldView::recieveNotification() - we cannot get here.");
356 break;
357 }
358 } else if (dynamic_cast<AtomObservable *>(publisher) != NULL) {
359 switch (notification->getChannelNo()) {
360 case AtomObservable::PositionChanged:
361 {
362 const atom *_atom = dynamic_cast<const atom *>(publisher);
363 #ifdef LOG_OBSERVER
364 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_atom->getId())+" has changed its position.";
365 #endif
366 emit changed();
367 break;
368 }
369 default:
370 ASSERT(0, "GLWorldView::recieveNotification() - we cannot get here.");
371 break;
372 }
373 } else if (static_cast<ShapeRegistry*>(publisher) == ShapeRegistry::getPointer()) {
374 switch (notification->getChannelNo()) {
375 case ShapeRegistry::ShapeInserted:
376 {
377 worldscene->addShape(*ShapeRegistry::getInstance().lastChanged());
378 break;
379 }
380 case ShapeRegistry::ShapeRemoved:
381 {
382 worldscene->removeShape(*ShapeRegistry::getInstance().lastChanged());
383 break;
384 }
385 case ShapeRegistry::SelectionChanged:
386 {
387 worldscene->updateSelectedShapes();
388 break;
389 }
390 default:
391 ASSERT(0, "GLWorldView::recieveNotification() - we cannot get here.");
392 break;
393 }
394 } else
395 ASSERT(0, "GLWorldView::recieveNotification() - received notification from unknown source.");
396}
397
398void GLWorldView::checkChanges()
399{
400 updateGL();
401 needsRedraw = false;
402}
403
404void GLWorldView::sceneChangeSignalled()
405{
406 if (!needsRedraw){
407 redrawTimer->singleShot(0, this, SLOT(checkChanges()));
408 needsRedraw = true;
409 redrawTimer->start();
410 }
411}
412
413void GLWorldView::initializeGL(QGLPainter *painter)
414{
415 worldscene->initialize(this, painter);
416 changesPresent = false;
417}
418
419void GLWorldView::paintGL(QGLPainter *painter)
420{
421 if (changesPresent) {
422 initializeGL(painter);
423 changesPresent = false;
424 }
425
426 QVector3D cameraDir = camera()->center() - camera()->eye();
427 cameraDir.normalize();
428 QVector4D cameraPlane(cameraDir, QVector3D::dotProduct(cameraDir, camera()->eye()));
429 worldscene->draw(painter, cameraPlane);
430
431 drawDreiBein(painter);
432
433 // Domain box has to be last because of its transparency.
434 drawDomainBox(painter);
435}
436
437void GLWorldView::keyPressEvent(QKeyEvent *e)
438{
439 if (e->key() == Qt::Key_Tab) {
440 // The Tab key turns the ShowPicking option on and off,
441 // which helps show what the pick buffer looks like.
442 setOption(QGLView::ShowPicking, ((options() & QGLView::ShowPicking) == 0));
443 updateGL();
444 }
445 QGLView::keyPressEvent(e);
446}
447
448void GLWorldView::changeSignalled()
449{
450 changesPresent = true;
451}
452
453
454/**
455 * Set the current camera control mode.
456 */
457void GLWorldView::setCameraControlMode(GLWorldView::CameraControlModeType mode)
458{
459 cameraControlMode = mode;
460}
461
462void GLWorldView::setCameraControlModeRotation()
463{
464 setCameraControlMode(Rotate);
465}
466
467void GLWorldView::setCameraControlModeTranslation()
468{
469 setCameraControlMode(Translate);
470}
471
472/**
473 * Returns the current camera control mode.
474 * This needs to be invertable (rotation - translation), if the shift key is pressed.
475 */
476GLWorldView::CameraControlModeType GLWorldView::getCameraControlMode(bool inverted)
477{
478 if (inverted){
479 if (cameraControlMode == Rotate)
480 return Translate;
481 if (cameraControlMode == Translate)
482 return Rotate;
483 return Rotate;
484 }else
485 return cameraControlMode;
486}
487
488/**
489 * Set the camera so it can oversee the whole domain.
490 */
491void GLWorldView::fitCameraToDomain()
492{
493 // Move the camera focus point to the center of the domain box.
494 Vector v = World::getInstance().getDomain().translateIn(Vector(0.5, 0.5, 0.5));
495 camera()->setCenter(QVector3D(v[0], v[1], v[2]));
496
497 // Guess some eye distance.
498 double dist = v.Norm() * 3;
499 camera()->setEye(QVector3D(v[0], v[1], v[2] + dist));
500 camera()->setUpVector(QVector3D(0, 1, 0));
501}
502
503void GLWorldView::setCameraStereoModeDisable()
504{
505 setStereoType(QGLView::Hardware);
506 camera()->setEyeSeparation(0.0);
507 updateGL();
508}
509
510void GLWorldView::setCameraStereoModeHardware()
511{
512 setStereoType(QGLView::Hardware);
513 camera()->setEyeSeparation(defaultEyeSeparation);
514 updateGL();
515}
516
517void GLWorldView::setCameraStereoModeLeftRight()
518{
519 setStereoType(QGLView::LeftRight);
520 camera()->setEyeSeparation(defaultEyeSeparation);
521 updateGL();
522}
523
524void GLWorldView::setCameraStereoModeRightLeft()
525{
526 setStereoType(QGLView::RightLeft);
527 camera()->setEyeSeparation(defaultEyeSeparation);
528 updateGL();
529}
530
531void GLWorldView::setCameraStereoModeTopBottom()
532{
533 setStereoType(QGLView::TopBottom);
534 camera()->setEyeSeparation(defaultEyeSeparation);
535 updateGL();
536}
537
538void GLWorldView::setCameraStereoModeBottomTop()
539{
540 setStereoType(QGLView::BottomTop);
541 camera()->setEyeSeparation(defaultEyeSeparation);
542 updateGL();
543}
544
545void GLWorldView::setCameraStereoModeAnaglyph()
546{
547 setStereoType(QGLView::RedCyanAnaglyph);
548 camera()->setEyeSeparation(defaultEyeSeparation);
549 updateGL();
550}
551
552void GLWorldView::mousePressEvent(QMouseEvent *event)
553{
554 QGLView::mousePressEvent(event);
555
556 // Reset the saved mouse position.
557 lastMousePos = event->posF();
558}
559
560/**
561 * Handle a mouse move event.
562 * This is used to control the camera (rotation and translation) when the left button is being pressed.
563 */
564void GLWorldView::mouseMoveEvent(QMouseEvent *event)
565{
566 if (event->buttons() & Qt::LeftButton){
567 // Find the mouse distance since the last event.
568 QPointF d = event->posF() - lastMousePos;
569 lastMousePos = event->posF();
570
571 // Rotate or translate? (inverted by shift key)
572 CameraControlModeType mode = getCameraControlMode(event->modifiers() & Qt::ShiftModifier);
573
574 if (mode == Rotate){
575 // Rotate the camera.
576 d *= 0.3;
577 camera()->tiltPanRollCenter(- d.y(), - d.x(), 0);
578 }else if (mode == Translate){
579 // Translate the camera.
580 d *= 0.02;
581 camera()->translateCenter(- d.x(), d.y(), 0);
582 camera()->translateEye(- d.x(), d.y(), 0);
583 }
584 }else{
585 // Without this Qt would not test for hover events (i.e. mouse over an atom).
586 QGLView::mouseMoveEvent(event);
587 }
588}
589
590/**
591 * When the mouse wheel is used, zoom in or out.
592 */
593void GLWorldView::wheelEvent(QWheelEvent *event)
594{
595 // Find the distance between the eye and focus point.
596 QVector3D d = camera()->eye() - camera()->center();
597
598 // Scale the distance.
599 if (event->delta() < 0)
600 d *= 1.2;
601 else if (event->delta() > 0)
602 d /= 1.2;
603
604 // Set new eye position.
605 camera()->setEye(camera()->center() + d);
606}
607
608/**
609 * Draw a transparent cube representing the domain.
610 */
611void GLWorldView::drawDomainBox(QGLPainter *painter) const
612{
613 // Apply the domain matrix.
614 RealSpaceMatrix m = World::getInstance().getDomain().getM();
615 painter->modelViewMatrix().push();
616 painter->modelViewMatrix() *= QMatrix4x4(m.at(0,0), m.at(0,1), m.at(0,2), 0.0,
617 m.at(1,0), m.at(1,1), m.at(1,2), 0.0,
618 m.at(2,0), m.at(2,1), m.at(2,2), 0.0,
619 0.0, 0.0, 0.0, 1.0);
620
621 // Draw the transparent cube.
622 painter->setStandardEffect(QGL::LitMaterial);
623 glCullFace(GL_BACK);
624 glEnable(GL_CULL_FACE);
625 glEnable(GL_BLEND);
626 glDepthMask(0);
627 //glDisable(GL_DEPTH_TEST);
628 meshDomainBox->draw(painter);
629 //glEnable(GL_DEPTH_TEST);
630 glDepthMask(1);
631 glDisable(GL_BLEND);
632 glDisable(GL_CULL_FACE);
633
634 // Draw the outlines.
635 painter->setFaceMaterial(QGL::AllFaces, domainBoxMaterial);
636 //glEnable(GL_LINE_SMOOTH);
637 QVector3DArray array;
638 array.append(0, 0, 0); array.append(1, 0, 0);
639 array.append(1, 0, 0); array.append(1, 1, 0);
640 array.append(1, 1, 0); array.append(0, 1, 0);
641 array.append(0, 1, 0); array.append(0, 0, 0);
642
643 array.append(0, 0, 1); array.append(1, 0, 1);
644 array.append(1, 0, 1); array.append(1, 1, 1);
645 array.append(1, 1, 1); array.append(0, 1, 1);
646 array.append(0, 1, 1); array.append(0, 0, 1);
647
648 array.append(0, 0, 0); array.append(0, 0, 1);
649 array.append(1, 0, 0); array.append(1, 0, 1);
650 array.append(0, 1, 0); array.append(0, 1, 1);
651 array.append(1, 1, 0); array.append(1, 1, 1);
652 painter->clearAttributes();
653 painter->setVertexAttribute(QGL::Position, array);
654 painter->draw(QGL::Lines, 24);
655
656 painter->modelViewMatrix().pop();
657}
658
659void GLWorldView::drawDreiBein(QGLPainter *painter)
660{
661 painter->modelViewMatrix().push();
662 painter->modelViewMatrix().translate(camera()->center());
663 painter->setStandardEffect(QGL::LitMaterial);
664 painter->setFaceMaterial(QGL::FrontFaces, NULL);
665 meshDreiBein->draw(painter);
666 painter->modelViewMatrix().pop();
667}
668
669void GLWorldView::sceneHoverSignalled(const atom *_atom)
670{
671 emit hoverChanged(_atom);
672}
673
674
675//#include <GL/glu.h>
676//#include <QtGui/qslider.h>
677//#include <QtGui/qevent.h>
678//
679//#include "ui_dialoglight.h"
680//
681//#include "CodePatterns/MemDebug.hpp"
682//
683//#include <iostream>
684//#include <boost/shared_ptr.hpp>
685//
686//#include "LinearAlgebra/Line.hpp"
687//#include "Atom/atom.hpp"
688//#include "Bond/bond.hpp"
689//#include "Element/element.hpp"
690//#include "molecule.hpp"
691//#include "Element/periodentafel.hpp"
692//#include "World.hpp"
693//
694//#if defined(Q_CC_MSVC)
695//#pragma warning(disable:4305) // init: truncation from const double to float
696//#endif
697//
698//
699//GLMoleculeView::GLMoleculeView(QWidget *parent) :
700// QGLWidget(parent), Observer("GLMoleculeView"), X(Vector(1,0,0)), Y(Vector(0,1,0)), Z(Vector(0,0,1))
701//{
702// xRot = yRot = zRot = 0.0; // default object rotation
703// scale = 5.; // default object scale
704// object = 0;
705// LightPosition[0] = 0.0f;
706// LightPosition[1] = 2.0f;
707// LightPosition[2] = 2.0f;
708// LightPosition[3] = 0.0f;
709// LightDiffuse[0] = 0.5f;
710// LightDiffuse[1] = 0.5f;
711// LightDiffuse[2] = 0.5f;
712// LightDiffuse[3] = 0.0f;
713// LightAmbient[0] = 0.0f;
714// LightAmbient[1] = 0.0f;
715// LightAmbient[2] = 0.0f;
716// LightAmbient[3] = 0.0f;
717//
718// SelectionColor[0] = 0;
719// SelectionColor[1] = 128;
720// SelectionColor[2] = 128;
721//
722// MultiViewEnabled = true;
723//
724// isSignaller = false;
725//
726// World::getInstance().signOn(this);
727//}
728//
729///** Destructor of GLMoleculeView.
730// * Free's the CallList.
731// */
732//GLMoleculeView::~GLMoleculeView()
733//{
734// makeCurrent();
735// glDeleteLists( object, 1 );
736//
737// World::getInstance().signOff(this);
738//}
739//
740///** Paints the conents of the OpenGL window.
741// * Clears the GL buffers, enables lighting and depth.
742// * Window is either quartered (if GLMoleculeView::MultiViewEnabled) and xy, xz, yz planar views
743// * are added. Uses the CallList, constructed during InitializeGL().
744// */
745//void GLMoleculeView::paintGL()
746//{
747// Vector spot;
748//
749// glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
750// glShadeModel(GL_SMOOTH); // Enable Smooth Shading
751// glEnable(GL_LIGHTING); // Enable Light One
752// glEnable(GL_DEPTH_TEST); // Enables Depth Testing
753// glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
754// glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
755//
756// // 3d viewport
757// if (MultiViewEnabled)
758// glViewport( 0, 0, (GLint)width/2, (GLint)height/2 );
759// else
760// glViewport( 0, 0, (GLint)width, (GLint)height );
761// glMatrixMode( GL_PROJECTION );
762// glLoadIdentity();
763// glFrustum( -1.0, 1.0, -1.0, 1.0, 1.0, 50.0 );
764// glMatrixMode( GL_MODELVIEW );
765// glLoadIdentity();
766//
767// // calculate point of view and direction
768// glTranslated(position[0],position[1],position[2]);
769// glTranslated(0.0, 0.0, -scale);
770// glRotated(xRot, 1.0, 0.0, 0.0);
771// glRotated(yRot, 0.0, 1.0, 0.0);
772// glRotated(zRot, 0.0, 0.0, 1.0);
773//
774// // render scene
775// glCallList(object);
776//
777// // enable light
778// glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
779// glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
780// glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light
781// glEnable(GL_LIGHT1); // Enable Light One
782//
783// if (MultiViewEnabled) {
784// // xy view port
785// glViewport( (GLint)width/2, 0, (GLint)width/2, (GLint)height/2 );
786// glMatrixMode( GL_PROJECTION );
787// glLoadIdentity();
788// glScalef(1./scale, 1./scale,1./scale);
789// glOrtho(0, width/2, 0, height/2, 0,0);
790// glMatrixMode( GL_MODELVIEW );
791// glLoadIdentity();
792//
793// // calculate point of view and direction
794// view = position;
795// spot = Vector(0.,0.,scale);
796// top = Vector(0.,1.,0.);
797// gluLookAt(
798// spot[0], spot[1], spot[2],
799// view[0], view[1], view[2],
800// top[0], top[1], top[2]);
801//
802// // enable light
803// glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
804// glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
805// glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light
806// glEnable(GL_LIGHT1); // Enable Light One
807//
808// // render scene
809// glCallList(object);
810//
811// // xz viewport
812// glViewport( 0, (GLint)height/2, (GLint)width/2, (GLint)height/2 );
813// glMatrixMode( GL_PROJECTION );
814// glLoadIdentity();
815// glScalef(1./scale, 1./scale,1./scale);
816// glOrtho(0, width/2, 0, height/2, 0,0);
817// glMatrixMode( GL_MODELVIEW );
818// glLoadIdentity();
819//
820// // calculate point of view and direction
821// view = position;
822// spot = Vector(0.,scale,0.);
823// top = Vector(1.,0.,0.);
824// gluLookAt(
825// spot[0], spot[1], spot[2],
826// view[0], view[1], view[2],
827// top[0], top[1], top[2]);
828//
829// // enable light
830// glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
831// glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
832// glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light
833// glEnable(GL_LIGHT1); // Enable Light One
834//
835// // render scene
836// glCallList(object);
837//
838// //yz viewport
839// glViewport( (GLint)width/2, (GLint)height/2, (GLint)width/2, (GLint)height/2 );
840// glMatrixMode( GL_PROJECTION );
841// glLoadIdentity();
842// glScalef(1./scale, 1./scale,1./scale);
843// glOrtho(0, width/2, 0, height/2, 0,0);
844// glMatrixMode( GL_MODELVIEW );
845// glLoadIdentity();
846//
847// // calculate point of view and direction
848// view= position;
849// spot = Vector(scale,0.,0.);
850// top = Vector(0.,1.,0.);
851// gluLookAt(
852// spot[0], spot[1], spot[2],
853// view[0], view[1], view[2],
854// top[0], top[1], top[2]);
855//
856// // enable light
857// glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
858// glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
859// glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light
860// glEnable(GL_LIGHT1); // Enable Light One
861//
862// // render scene
863// glCallList(object);
864// }
865// //CoordinatesBar->setText( QString ("X: %1, Y: %2, Z: %3").arg(position[0]).arg(position[1]).arg(position[2]) );
866//}
867//
868////void polarView{GLdouble distance, GLdouble twist,
869//// GLdouble elevation, GLdouble azimuth)
870////{
871//// glTranslated(0.0, 0.0, -distance);
872//// glRotated(-twist, 0.0, 0.0, 1.0);
873//// glRotated(-elevation, 1.0, 0.0, 0.0);
874//// glRotated(azimuth, 0.0, 0.0, 1.0);
875////}
876//
877///** Make a sphere.
878// * \param x position
879// * \param radius radius
880// * \param color[3] color rgb values
881// */
882//void GLMoleculeView::makeSphere(const Vector &x, double radius, const unsigned char color[3])
883//{
884// float blueMaterial[] = { 255./(float)color[0], 255./(float)color[1], 255./(float)color[2], 1 }; // need to recast from [0,255] with integers into [0,1] with floats
885// GLUquadricObj* q = gluNewQuadric ();
886// gluQuadricOrientation(q, GLU_OUTSIDE);
887//
888// std::cout << "Setting sphere at " << x << " with color r"
889// << (int)color[0] << ",g" << (int)color[1] << ",b" << (int)color[2] << "." << endl;
890//
891// glPushMatrix();
892// glTranslatef( x[0], x[1], x[2]);
893//// glRotatef( xRot, 1.0, 0.0, 0.0);
894//// glRotatef( yRot, 0.0, 1.0, 0.0);
895//// glRotatef( zRot, 0.0, 0.0, 1.0);
896// glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blueMaterial);
897// gluSphere (q, (GLdouble)radius, 10, 10);
898// glPopMatrix();
899//}
900//
901///** Make a cylinder.
902// * \param x origin
903// * \param y direction
904// * \param radius thickness
905// * \param height length
906// * \color[3] color rgb values
907// */
908//void GLMoleculeView::makeCylinder(const Vector &x, const Vector &y, double radius, double height, const unsigned char color[3])
909//{
910// float blueMaterial[] = { 255./(float)color[0], 255./(float)color[1], 255./(float)color[2], 1 };
911// GLUquadricObj* q = gluNewQuadric ();
912// gluQuadricOrientation(q, GLU_OUTSIDE);
913// Vector a,b;
914// Vector OtherAxis;
915// double alpha;
916// a = x - y;
917// // construct rotation axis
918// b = a;
919// b.VectorProduct(Z);
920// Line axis(zeroVec, b);
921// // calculate rotation angle
922// alpha = a.Angle(Z);
923// // construct other axis to check right-hand rule
924// OtherAxis = b;
925// OtherAxis.VectorProduct(Z);
926// // assure right-hand rule for the rotation
927// if (a.ScalarProduct(OtherAxis) < MYEPSILON)
928// alpha = M_PI-alpha;
929// // check
930// Vector a_rotated = axis.rotateVector(a, alpha);
931// std::cout << "Setting cylinder from "// << x << " to " << y
932// << a << " to " << a_rotated << " around " << b << " by " << alpha/M_PI*180. << ", respectively, "
933// << " with color r"
934// << (int)color[0] << ",g" << (int)color[1] << ",b" << (int)color[2] << "." << endl;
935//
936// glPushMatrix();
937// glTranslatef( x[0], x[1], x[2]);
938// glRotatef( alpha/M_PI*180., b[0], b[1], b[2]);
939// glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blueMaterial);
940// gluCylinder (q, (GLdouble)radius, (GLdouble)radius, (GLdouble)height, 10, 10);
941// glPopMatrix();
942//}
943//
944///** Defines the display CallList.
945// * Goes through all molecules and their atoms and adds spheres for atoms and cylinders
946// * for bonds. Heeds GLMoleculeView::SelectedAtom and GLMoleculeView::SelectedMolecule.
947// */
948//void GLMoleculeView::initializeGL()
949//{
950// double x[3] = {-1, 0, -10};
951// unsigned char white[3] = {255,255,255};
952// Vector Position, OtherPosition;
953// QSize window = size();
954// width = window.width();
955// height = window.height();
956// std::cout << "Setting width to " << width << " and height to " << height << std::endl;
957// GLfloat shininess[] = { 0.0 };
958// GLfloat specular[] = { 0, 0, 0, 1 };
959// glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Let OpenGL clear to black
960// object = glGenLists(1);
961// glNewList( object, GL_COMPILE );
962// glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
963// glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
964//
965// const std::vector<molecule*> &molecules = World::getInstance().getAllMolecules();
966//
967// if (molecules.size() > 0) {
968// for (std::vector<molecule*>::const_iterator Runner = molecules.begin();
969// Runner != molecules.end();
970// Runner++) {
971// for (molecule::const_iterator atomiter = (*Runner)->begin();
972// atomiter != (*Runner)->end();
973// ++atomiter) {
974// // create atom
975// const element *ptr = (*atomiter)->getType();
976// boost::shared_ptr<Vector> MolCenter((*Runner)->DetermineCenterOfGravity());
977// Position = (*atomiter)->getPosition() - *MolCenter;
978// const unsigned char* color = NULL;
979// if ((World::getInstance().isSelected(*atomiter)) || (World::getInstance().isSelected((*Runner))))
980// color = SelectionColor;
981// else
982// color = ptr->getColor();
983// makeSphere(Position, ptr->getVanDerWaalsRadius()*0.25, color);
984//
985// // create bonds
986// const BondList &bonds = (*atomiter)->getListOfBonds();
987// for (BondList::const_iterator bonditer = bonds.begin();
988// bonditer != bonds.end();
989// ++bonditer) {
990// if ((*bonditer)->leftatom->getId() == (*atomiter)->getId()) {
991// Position = (*bonditer)->leftatom->getPosition() - *MolCenter;
992// OtherPosition = (*bonditer)->rightatom->getPosition() - *MolCenter;
993// const double distance = sqrt(Position.DistanceSquared(OtherPosition))/2.;
994// const unsigned char *color1 = (*bonditer)->leftatom->getType()->getColor();
995// const unsigned char *color2 = (*bonditer)->rightatom->getType()->getColor();
996// makeCylinder(Position, OtherPosition, 0.1, distance, color1);
997// makeCylinder(OtherPosition, Position, 0.1, distance, color2);
998// }
999// }
1000// }
1001// }
1002// } else {
1003// makeSphere( x,1, white);
1004// }
1005// glEndList();
1006//}
1007//
1008//
1009///* ================================== SLOTS ============================== */
1010//
1011///** Initializes some public variables.
1012// * \param *ptr pointer to QLabel statusbar
1013// */
1014//void GLMoleculeView::init(QLabel *ptr)
1015//{
1016// StatusBar = ptr;
1017//}
1018//
1019///** Initializes the viewport statusbar.
1020// * \param *ptr pointer to QLabel for showing view pointcoordinates.
1021// */
1022//void GLMoleculeView::initCoordinates(QLabel *ptr)
1023//{
1024// CoordinatesBar = ptr;
1025//}
1026//
1027///** Slot to be called when to initialize GLMoleculeView::MolData.
1028// */
1029//void GLMoleculeView::createView( )
1030//{
1031// initializeGL();
1032// updateGL();
1033//}
1034//
1035///** Slot of window is resized.
1036// * Copies new width and height to GLMoleculeView::width and GLMoleculeView::height and calls updateGL().
1037// * \param w new width of window
1038// * \param h new height of window
1039// */
1040//void GLMoleculeView::resizeGL( int w, int h )
1041//{
1042// width = w;
1043// height = h;
1044// updateGL();
1045//}
1046//
1047///** Sets x rotation angle.
1048// * sets GLMoleculeView::xRot and calls updateGL().
1049// * \param degrees new rotation angle in degrees
1050// */
1051//void GLMoleculeView::setXRotation( int degrees )
1052//{
1053// xRot = (GLfloat)(degrees % 360);
1054// updateGL();
1055//}
1056//
1057//
1058///** Sets y rotation angle.
1059// * sets GLMoleculeView::yRot and calls updateGL().
1060// * \param degrees new rotation angle in degrees
1061// */
1062//void GLMoleculeView::setYRotation( int degrees )
1063//{
1064// yRot = (GLfloat)(degrees % 360);
1065// updateGL();
1066//}
1067//
1068//
1069///** Sets z rotation angle.
1070// * sets GLMoleculeView::zRot and calls updateGL().
1071// * \param degrees new rotation angle in degrees
1072// */
1073//void GLMoleculeView::setZRotation( int degrees )
1074//{
1075// zRot = (GLfloat)(degrees % 360);
1076// updateGL();
1077//}
1078//
1079///** Sets the scale of the scene.
1080// * sets GLMoleculeView::scale and calls updateGL().
1081// * \param distance distance divided by 100 is the new scale
1082// */
1083//void GLMoleculeView::setScale( int distance )
1084//{
1085// scale = (GLfloat)(distance / 100.);
1086// updateGL();
1087//}
1088//
1089///** Update the ambient light.
1090// * \param light[4] light strength per axis and position (w)
1091// */
1092//void GLMoleculeView::setLightAmbient( int *light )
1093//{
1094// for(int i=0;i<4;i++)
1095// LightAmbient[i] = light[i];
1096// updateGL();
1097//}
1098//
1099///** Update the diffuse light.
1100// * \param light[4] light strength per axis and position (w)
1101// */
1102//void GLMoleculeView::setLightDiffuse( int *light )
1103//{
1104// for(int i=0;i<4;i++)
1105// LightDiffuse[i] = light[i];
1106// updateGL();
1107//}
1108//
1109///** Update the position of light.
1110// * \param light[4] light strength per axis and position (w)
1111// */
1112//void GLMoleculeView::setLightPosition( int *light )
1113//{
1114// for(int i=0;i<4;i++)
1115// LightPosition[i] = light[i];
1116// updateGL();
1117//}
1118//
1119///** Toggles the boolean GLMoleculeView::MultiViewEnabled.
1120// * Flips the boolean and calls updateGL().
1121// */
1122//void GLMoleculeView::toggleMultiViewEnabled ( )
1123//{
1124// MultiViewEnabled = !MultiViewEnabled;
1125// cout << "Setting MultiView to " << MultiViewEnabled << "." << endl;
1126// updateGL();
1127//}
1128//
1129///** Launch a dialog to configure the lights.
1130// */
1131//void GLMoleculeView::createDialogLight()
1132//{
1133//// Ui_DialogLight *Lights = new Ui_DialogLight();
1134//// if (Lights == NULL)
1135//// return;
1136//// // Set up the dynamic dialog here
1137//// QLineEdit *Field = NULL;
1138//// Field = Lights->findChild<QLineEdit *>("LightPositionX");
1139//// if (Field) Field->setText( QString("%1").arg(LightPosition[0]) );
1140//// Field = Lights->findChild<QLineEdit *>("LightPositionY");
1141//// if (Field) Field->setText( QString("%1").arg(LightPosition[1]) );
1142//// Field = Lights->findChild<QLineEdit *>("LightPositionZ");
1143//// if (Field) Field->setText( QString("%1").arg(LightPosition[2]) );
1144//// Field = Lights->findChild<QLineEdit *>("LightPositionW");
1145//// if (Field) Field->setText( QString("%1").arg(LightPosition[3]) );
1146////
1147//// Field = Lights->findChild<QLineEdit *>("LightDiffuseX");
1148//// if (Field) Field->setText( QString("%1").arg(LightDiffuse[0]) );
1149//// Field = Lights->findChild<QLineEdit *>("LightDiffuseY");
1150//// if (Field) Field->setText( QString("%1").arg(LightDiffuse[1]) );
1151//// Field = Lights->findChild<QLineEdit *>("LightDiffuseZ");
1152//// if (Field) Field->setText( QString("%1").arg(LightDiffuse[2]) );
1153//// Field = Lights->findChild<QLineEdit *>("LightDiffuseW");
1154//// if (Field) Field->setText( QString("%1").arg(LightDiffuse[3]) );
1155////
1156//// Field = Lights->findChild<QLineEdit *>("LightAmbientX");
1157//// if (Field) Field->setText( QString("%1").arg(LightAmbient[0]) );
1158//// Field = Lights->findChild<QLineEdit *>("LightAmbientY");
1159//// if (Field) Field->setText( QString("%1").arg(LightAmbient[1]) );
1160//// Field = Lights->findChild<QLineEdit *>("LightAmbientZ");
1161//// if (Field) Field->setText( QString("%1").arg(LightAmbient[2]) );
1162//// Field = Lights->findChild<QLineEdit *>("LightAmbientW");
1163//// if (Field) Field->setText( QString("%1").arg(LightAmbient[3]) );
1164////
1165//// if ( Lights->exec() ) {
1166//// //cout << "User accepted.\n";
1167//// // The user accepted, act accordingly
1168//// Field = Lights->findChild<QLineEdit *>("LightPositionX");
1169//// if (Field) LightPosition[0] = Field->text().toDouble();
1170//// Field = Lights->findChild<QLineEdit *>("LightPositionY");
1171//// if (Field) LightPosition[1] = Field->text().toDouble();
1172//// Field = Lights->findChild<QLineEdit *>("LightPositionZ");
1173//// if (Field) LightPosition[2] = Field->text().toDouble();
1174//// Field = Lights->findChild<QLineEdit *>("LightPositionW");
1175//// if (Field) LightPosition[3] = Field->text().toDouble();
1176////
1177//// Field = Lights->findChild<QLineEdit *>("LightDiffuseX");
1178//// if (Field) LightDiffuse[0] = Field->text().toDouble();
1179//// Field = Lights->findChild<QLineEdit *>("LightDiffuseY");
1180//// if (Field) LightDiffuse[1] = Field->text().toDouble();
1181//// Field = Lights->findChild<QLineEdit *>("LightDiffuseZ");
1182//// if (Field) LightDiffuse[2] = Field->text().toDouble();
1183//// Field = Lights->findChild<QLineEdit *>("LightDiffuseW");
1184//// if (Field) LightDiffuse[3] = Field->text().toDouble();
1185////
1186//// Field = Lights->findChild<QLineEdit *>("LightAmbientX");
1187//// if (Field) LightAmbient[0] = Field->text().toDouble();
1188//// Field = Lights->findChild<QLineEdit *>("LightAmbientY");
1189//// if (Field) LightAmbient[1] = Field->text().toDouble();
1190//// Field = Lights->findChild<QLineEdit *>("LightAmbientZ");
1191//// if (Field) LightAmbient[2] = Field->text().toDouble();
1192//// Field = Lights->findChild<QLineEdit *>("LightAmbientW");
1193//// if (Field) LightAmbient[3] = Field->text().toDouble();
1194//// updateGL();
1195//// } else {
1196//// //cout << "User reclined.\n";
1197//// }
1198//// delete(Lights);
1199//}
1200//
1201///** Slot for event of pressed mouse button.
1202// * Switch discerns between buttons and stores position of event in GLMoleculeView::LeftButtonPos,
1203// * GLMoleculeView::MiddleButtonPos or GLMoleculeView::RightButtonPos.
1204// * \param *event structure containing information of the event
1205// */
1206//void GLMoleculeView::mousePressEvent(QMouseEvent *event)
1207//{
1208// std::cout << "MousePressEvent." << endl;
1209// QPoint *pos = NULL;
1210// switch (event->button()) { // get the right array
1211// case Qt::LeftButton:
1212// pos = &LeftButtonPos;
1213// std::cout << "Left Button" << endl;
1214// break;
1215// case Qt::MidButton:
1216// pos = &MiddleButtonPos;
1217// std::cout << "Middle Button" << endl;
1218// break;
1219// case Qt::RightButton:
1220// pos = &RightButtonPos;
1221// std::cout << "Right Button" << endl;
1222// break;
1223// default:
1224// break;
1225// }
1226// if (pos) { // store the position
1227// pos->setX(event->pos().x());
1228// pos->setY(event->pos().y());
1229// std::cout << "Stored src position is (" << pos->x() << "," << pos->y() << ")." << endl;
1230// } else {
1231// std::cout << "pos is NULL." << endl;
1232// }
1233//}
1234//
1235///** Slot for event of pressed mouse button.
1236// * Switch discerns between buttons:
1237// * -# Left Button: Rotates the view of the GLMoleculeView, relative to GLMoleculeView::LeftButtonPos.
1238// * -# Middle Button: nothing
1239// * -# Right Button: Shifts the selected molecule or atom, relative to GLMoleculeView::RightButtonPos.
1240// * \param *event structure containing information of the event
1241// */
1242//void GLMoleculeView::mouseReleaseEvent(QMouseEvent *event)
1243//{
1244// std::cout << "MouseReleaseEvent." << endl;
1245// QPoint *srcpos = NULL;
1246// QPoint destpos = event->pos();
1247// int Width = (MultiViewEnabled) ? width/2 : width;
1248// int Height = (MultiViewEnabled) ? height/2 : height;
1249// std::cout << "Received dest position is (" << destpos.x() << "," << destpos.y() << ")." << endl;
1250// switch (event->button()) { // get the right array
1251// case Qt::LeftButton: // LeftButton rotates the view
1252// srcpos = &LeftButtonPos;
1253// std::cout << "Left Button" << endl;
1254// if (srcpos) { // subtract the position and act
1255// std::cout << "Stored src position is (" << srcpos->x() << "," << srcpos->y() << ")." << endl;
1256// destpos -= *srcpos;
1257// std::cout << "Resulting diff position is (" << destpos.x() << "," << destpos.y() << ")." << endl;
1258// std::cout << "Width and Height are " << Width << "," << Height << "." << endl;
1259//
1260// int pos = (int)floor((double)srcpos->x()/(double)Width) + ((int)floor((double)srcpos->y()/(double)Height))*2;
1261// if ((MultiViewEnabled) && (pos != 2)) { // means four regions, and we are in a shifting one
1262// // switch between three regions
1263// // decide into which of the four screens the initial click has been made
1264// std::cout << "Position is " << pos << "." << endl;
1265// switch(pos) {
1266// case 0: // lower left = xz
1267// position[0] += -destpos.y()/100.;
1268// position[2] += destpos.x()/100.;
1269// break;
1270// case 1: // lower right = yz
1271// position[1] += -destpos.y()/100.;
1272// position[2] += -destpos.x()/100.;
1273// break;
1274// case 2: // upper left = projected
1275// std::cout << "This is impossible: Shifting in the projected region, we should rotate!." << endl;
1276// break;
1277// case 3: // upper right = xy
1278// position[0] += destpos.x()/100.;
1279// position[1] += -destpos.y()/100.;
1280// break;
1281// default:
1282// std::cout << "click was not in any of the four regions." << endl;
1283// break;
1284// }
1285// updateGL();
1286// } else { // we are in rotation region
1287// QWidget *Parent = parentWidget();
1288// QSlider *sliderX = Parent->findChild<QSlider *>("sliderX");
1289// QSlider *sliderY = Parent->findChild<QSlider *>("sliderY");
1290// std::cout << sliderX << " and " << sliderY << endl;
1291// if (sliderX) {
1292// int xrange = sliderX->maximum() - sliderX->minimum();
1293// double xValue = ((destpos.x() + Width) % Width);
1294// xValue *= (double)xrange/(double)Width;
1295// xValue += sliderX->value();
1296// int xvalue = (int) xValue % xrange;
1297// std::cout << "Setting x to " << xvalue << " within range " << xrange << "." << endl;
1298// setXRotation(xvalue);
1299// sliderX->setValue(xvalue);
1300// } else {
1301// std::cout << "sliderX is NULL." << endl;
1302// }
1303// if (sliderY) {
1304// int yrange = sliderY->maximum() - sliderY->minimum();
1305// double yValue = ((destpos.y() + Height) % Height);
1306// yValue *= (double)yrange/(double)Height;
1307// yValue += sliderY->value();
1308// int yvalue = (int) yValue % yrange;
1309// std::cout << "Setting y to " << yvalue << " within range " << yrange << "." << endl;
1310// setYRotation(yvalue);
1311// sliderY->setValue(yvalue);
1312// } else {
1313// std::cout << "sliderY is NULL." << endl;
1314// }
1315// }
1316// } else {
1317// std::cout << "srcpos is NULL." << endl;
1318// }
1319// break;
1320//
1321// case Qt::MidButton: // MiddleButton has no function so far
1322// srcpos = &MiddleButtonPos;
1323// std::cout << "Middle Button" << endl;
1324// if (srcpos) { // subtract the position and act
1325// QWidget *Parent = parentWidget();
1326// QSlider *sliderZ = Parent->findChild<QSlider *>("sliderZ");
1327// QSlider *sliderScale = Parent->findChild<QSlider *>("sliderScale");
1328// std::cout << sliderZ << " and " << sliderScale << endl;
1329// std::cout << "Stored src position is (" << srcpos->x() << "," << srcpos->y() << ")." << endl;
1330// destpos -= *srcpos;
1331// std::cout << "Resulting diff position is (" << destpos.x() << "," << destpos.y() << ")." << endl;
1332// std::cout << "Width and Height are " << Width << "," << Height << "." << endl;
1333// if (sliderZ) {
1334// int xrange = sliderZ->maximum() - sliderZ->minimum();
1335// double xValue = ((destpos.x() + Width) % Width);
1336// xValue *= (double)xrange/(double)Width;
1337// xValue += sliderZ->value();
1338// int xvalue = (int) xValue % xrange;
1339// std::cout << "Setting x to " << xvalue << " within range " << xrange << "." << endl;
1340// setZRotation(xvalue);
1341// sliderZ->setValue(xvalue);
1342// } else {
1343// std::cout << "sliderZ is NULL." << endl;
1344// }
1345// if (sliderScale) {
1346// int yrange = sliderScale->maximum() - sliderScale->minimum();
1347// double yValue = ((destpos.y() + Height) % Height);
1348// yValue *= (double)yrange/(double)Height;
1349// yValue += sliderScale->value();
1350// int yvalue = (int) yValue % yrange;
1351// std::cout << "Setting y to " << yvalue << " within range " << yrange << "." << endl;
1352// setScale(yvalue);
1353// sliderScale->setValue(yvalue);
1354// } else {
1355// std::cout << "sliderScale is NULL." << endl;
1356// }
1357// } else {
1358// std::cout << "srcpos is NULL." << endl;
1359// }
1360// break;
1361// break;
1362//
1363// case Qt::RightButton: // RightButton moves eitstdher the selected molecule or atom
1364// srcpos = &RightButtonPos;
1365// std::cout << "Right Button" << endl;
1366// if (srcpos) { // subtract the position and act
1367// std::cout << "Stored src position is (" << srcpos->x() << "," << srcpos->y() << ")." << endl;
1368// destpos -= *srcpos;
1369// std::cout << "Resulting diff position is (" << destpos.x() << "," << destpos.y() << ")." << endl;
1370// std::cout << "Width and Height are " << Width << "," << Height << "." << endl;
1371// if (MultiViewEnabled) {
1372// // which vector to change
1373// Vector SelectedPosition;
1374// const std::vector<atom*> &SelectedAtoms = World::getInstance().getSelectedAtoms();
1375// const std::vector<molecule*> &SelectedMolecules = World::getInstance().getSelectedMolecules();
1376// if (SelectedMolecules.size()) {
1377// if (SelectedAtoms.size())
1378// SelectedPosition = (*SelectedAtoms.begin())->getPosition();
1379// else
1380// SelectedPosition = (*(*SelectedMolecules.begin())->begin())->getPosition();
1381// }
1382// // decide into which of the four screens the initial click has been made
1383// int pos = (int)floor((double)srcpos->x()/(double)Width) + ((int)floor((double)srcpos->y()/(double)Height))*2;
1384// if (!SelectedPosition.IsZero()) {
1385// std::cout << "Position is " << pos << "." << endl;
1386// switch(pos) {
1387// case 0: // lower left = xz
1388// SelectedPosition[0] += -destpos.y()/100.;
1389// SelectedPosition[2] += destpos.x()/100.;
1390// break;
1391// case 1: // lower right = yz
1392// SelectedPosition[1] += -destpos.y()/100.;
1393// SelectedPosition[2] += -destpos.x()/100.;
1394// break;
1395// case 2: // upper left = projected
1396// SelectedPosition[0] += destpos.x()/100.;
1397// SelectedPosition[1] += destpos.y()/100.;
1398// SelectedPosition[2] += destpos.y()/100.;
1399// break;
1400// case 3: // upper right = xy
1401// SelectedPosition[0] += destpos.x()/100.;
1402// SelectedPosition[1] += -destpos.y()/100.;
1403// break;
1404// default:
1405// std::cout << "click was not in any of the four regions." << endl;
1406// break;
1407// }
1408// } else {
1409// std::cout << "Nothing selected." << endl;
1410// }
1411// // update Tables
1412// if (SelectedMolecules.size()) {
1413// isSignaller = true;
1414// if (SelectedAtoms.size())
1415// emit notifyAtomChanged( (*SelectedMolecules.begin()), (*SelectedAtoms.begin()), AtomPosition);
1416// else
1417// emit notifyMoleculeChanged( (*SelectedMolecules.begin()), MoleculePosition );
1418// }
1419// // update graphic
1420// initializeGL();
1421// updateGL();
1422// } else {
1423// cout << "MultiView is not enabled." << endl;
1424// }
1425// } else {
1426// cout << "srcpos is NULL." << endl;
1427// }
1428// break;
1429//
1430// default:
1431// break;
1432// }
1433//}
1434//
1435///* ======================================== SLOTS ================================ */
1436//
1437///** Hear announcement of selected molecule.
1438// * \param *mol pointer to selected molecule
1439// */
1440//void GLMoleculeView::hearMoleculeSelected(molecule *mol)
1441//{
1442// if (isSignaller) { // if we emitted the signal, return
1443// isSignaller = false;
1444// return;
1445// }
1446// initializeGL();
1447// updateGL();
1448//};
1449//
1450///** Hear announcement of selected atom.
1451// * \param *mol pointer to molecule containing atom
1452// * \param *Walker pointer to selected atom
1453// */
1454//void GLMoleculeView::hearAtomSelected(molecule *mol, atom *Walker)
1455//{
1456// if (isSignaller) { // if we emitted the signal, return
1457// isSignaller = false;
1458// return;
1459// }
1460// initializeGL();
1461// updateGL();
1462//};
1463//
1464///** Hear announcement of changed molecule.
1465// * \param *mol pointer to changed molecule
1466// * \param type of change
1467// */
1468//void GLMoleculeView::hearMoleculeChanged(molecule *mol, enum ChangesinMolecule type)
1469//{
1470// if (isSignaller) { // if we emitted the signal, return
1471// isSignaller = false;
1472// return;
1473// }
1474// initializeGL();
1475// updateGL();
1476//};
1477//
1478///** Hear announcement of changed atom.
1479// * \param *mol pointer to molecule containing atom
1480// * \param *Walker pointer to changed atom
1481// * \param type type of change
1482// */
1483//void GLMoleculeView::hearAtomChanged(molecule *mol, atom *Walker, enum ChangesinAtom type)
1484//{
1485// if (isSignaller) { // if we emitted the signal, return
1486// isSignaller = false;
1487// return;
1488// }
1489// initializeGL();
1490// updateGL();
1491//};
1492//
1493///** Hear announcement of changed element.
1494// * \param *Runner pointer to changed element
1495// * \param type of change
1496// */
1497//void GLMoleculeView::hearElementChanged(element *Runner, enum ChangesinElement type)
1498//{
1499// if (isSignaller) { // if we emitted the signal, return
1500// isSignaller = false;
1501// return;
1502// }
1503// switch(type) {
1504// default:
1505// case ElementName:
1506// case ElementSymbol:
1507// case ElementMass:
1508// case ElementValence:
1509// case ElementZ:
1510// break;
1511// case ElementCovalent:
1512// case ElementVanderWaals:
1513// initializeGL();
1514// updateGL();
1515// break;
1516// }
1517//};
1518//
1519///** Hear announcement of added molecule.
1520// * \param *mol pointer to added molecule
1521// */
1522//void GLMoleculeView::hearMoleculeAdded(molecule *mol)
1523//{
1524// if (isSignaller) { // if we emitted the signal, return
1525// isSignaller = false;
1526// return;
1527// }
1528// initializeGL();
1529// updateGL();
1530//};
1531//
1532///** Hear announcement of added atom.
1533// * \param *mol pointer to molecule containing atom
1534// * \param *Walker pointer to added atom
1535// */
1536//void GLMoleculeView::hearAtomAdded(molecule *mol, atom *Walker)
1537//{
1538// if (isSignaller) { // if we emitted the signal, return
1539// isSignaller = false;
1540// return;
1541// }
1542// initializeGL();
1543// updateGL();
1544//};
1545//
1546///** Hear announcement of removed molecule.
1547// * \param *mol pointer to removed molecule
1548// */
1549//void GLMoleculeView::hearMoleculeRemoved(molecule *mol)
1550//{
1551// if (isSignaller) { // if we emitted the signal, return
1552// isSignaller = false;
1553// return;
1554// }
1555// initializeGL();
1556// updateGL();
1557//};
1558//
1559///** Hear announcement of removed atom.
1560// * \param *mol pointer to molecule containing atom
1561// * \param *Walker pointer to removed atom
1562// */
1563//void GLMoleculeView::hearAtomRemoved(molecule *mol, atom *Walker)
1564//{
1565// if (isSignaller) { // if we emitted the signal, return
1566// isSignaller = false;
1567// return;
1568// }
1569// initializeGL();
1570// updateGL();
1571//};
1572//
1573//void GLMoleculeView::update(Observable *publisher)
1574//{
1575// initializeGL();
1576// updateGL();
1577//}
1578//
1579///**
1580// * This method is called when a special named change
1581// * of the Observable occured
1582// */
1583//void GLMoleculeView::recieveNotification(Observable *publisher, Notification_ptr notification)
1584//{
1585// initializeGL();
1586// updateGL();
1587//}
1588//
1589///**
1590// * This method is called when the observed object is destroyed.
1591// */
1592//void GLMoleculeView::subjectKilled(Observable *publisher)
1593//{
1594//
1595//}
1596//
1597//
1598//// new stuff
1599//
1600///** Returns the ref to the Material for element No \a from the map.
1601// *
1602// * \note We create a new one if the element is missing.
1603// *
1604// * @param no element no
1605// * @return ref to QGLMaterial
1606// */
1607//QGLMaterial* GLMoleculeView::getMaterial(size_t no)
1608//{
1609// if (ElementNoMaterialMap.find(no) != ElementNoMaterialMap.end()){
1610// // get present one
1611//
1612// } else {
1613// ASSERT( (no >= 0) && (no < MAX_ELEMENTS),
1614// "GLMoleculeView::getMaterial() - Element no "+toString(no)+" is invalid.");
1615// // create new one
1616// LOG(1, "Creating new material for element "+toString(no)+".");
1617// QGLMaterial *newmaterial = new QGLMaterial(this);
1618// periodentafel *periode = World::getInstance().getPeriode();
1619// element *desiredelement = periode->FindElement(no);
1620// ASSERT(desiredelement != NULL,
1621// "GLMoleculeView::getMaterial() - desired element "+toString(no)+" not present in periodentafel.");
1622// const unsigned char* color = desiredelement->getColor();
1623// newmaterial->setAmbientColor( QColor(color[0], color[1], color[2]) );
1624// newmaterial->setSpecularColor( QColor(60, 60, 60) );
1625// newmaterial->setShininess( QColor(128) );
1626// ElementNoMaterialMap.insert( no, newmaterial);
1627// }
1628//}
1629//
1630//QGLSceneNode* GLMoleculeView::getAtom(size_t no)
1631//{
1632// // first some sensibility checks
1633// ASSERT(World::getInstance().getAtom(AtomById(no)) != NULL,
1634// "GLMoleculeView::getAtom() - desired atom "
1635// +toString(no)+" not present in the World.");
1636// ASSERT(AtomsinSceneMap.find(no) != AtomsinSceneMap.end(),
1637// "GLMoleculeView::getAtom() - desired atom "
1638// +toString(no)+" not present in the AtomsinSceneMap.");
1639//
1640// return AtomsinSceneMap[no];
1641//}
1642//
1643//QGLSceneNode* GLMoleculeView::getBond(size_t leftno, size_t rightno)
1644//{
1645// // first some sensibility checks
1646// ASSERT(World::getInstance().getAtom(AtomById(leftno)) != NULL,
1647// "GLMoleculeView::getAtom() - desired atom "
1648// +toString(leftno)+" of bond not present in the World.");
1649// ASSERT(World::getInstance().getAtom(AtomById(rightno)) != NULL,
1650// "GLMoleculeView::getAtom() - desired atom "
1651// +toString(rightno)+" of bond not present in the World.");
1652// ASSERT(AtomsinSceneMap.find(leftno) != AtomsinSceneMap.end(),
1653// "GLMoleculeView::getAtom() - desired atom "
1654// +toString(leftno)+" of bond not present in the AtomsinSceneMap.");
1655// ASSERT(AtomsinSceneMap.find(rightno) != AtomsinSceneMap.end(),
1656// "GLMoleculeView::getAtom() - desired atom "
1657// +toString(rightno)+" of bond not present in the AtomsinSceneMap.");
1658// ASSERT(leftno == rightno,
1659// "GLMoleculeView::getAtom() - bond must not be between the same atom: "
1660// +toString(leftno)+" == "+toString(rightno)+".");
1661//
1662// // then return with smaller index first
1663// if (leftno > rightno)
1664// return AtomsinSceneMap[ make_pair(rightno, leftno) ];
1665// else
1666// return AtomsinSceneMap[ make_pair(leftno, rightno) ];
1667//}
1668//
Note: See TracBrowser for help on using the repository browser.