/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010-2012 University of Bonn. All rights reserved. * Copyright (C) 2013 Frederik Heber. All rights reserved. * * * This file is part of MoleCuilder. * * MoleCuilder is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * MoleCuilder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MoleCuilder. If not, see . */ /* * GLWorldView.cpp * * Created on: Aug 1, 2010 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "GLWorldView.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include "GLWorldScene.hpp" #include "CodePatterns/MemDebug.hpp" #include "Atom/AtomObserver.hpp" #include "Atom/atom_observable.hpp" #include "Box.hpp" #include "CodePatterns/Log.hpp" #include "CodePatterns/Observer/Notification.hpp" #include "CodePatterns/Observer/ObserverLog.hpp" #include "molecule.hpp" #include "Shapes/ShapeRegistry.hpp" #include "World.hpp" #include "WorldTime.hpp" GLWorldView::GLWorldView(QWidget *parent) : QGLView(parent), Observer("GLWorldView"), worldscene(NULL), changesPresent(false), needsRedraw(false) { worldscene = new GLWorldScene(this); setOption(QGLView::ObjectPicking, true); setOption(QGLView::CameraNavigation, false); setCameraControlMode(Rotate); defaultEyeSeparation = 4.0; createDomainBox(); createDreiBein(); //changeMaterials(false); qRegisterMetaType("atomicNumber_t"); connect(this, SIGNAL(ShapeAdded()), worldscene, SLOT(addShape())); connect(this, SIGNAL(ShapeRemoved()), worldscene, SLOT(removeShape())); connect(this, SIGNAL(TimeChanged()), worldscene, SIGNAL(updated())); connect(worldscene, SIGNAL(changeOccured()), this, SLOT(changeSignalled())); connect(worldscene, SIGNAL(changed()), this, SIGNAL(changed())); connect(worldscene, SIGNAL(hoverChanged(const atom *)), this, SLOT(sceneHoverSignalled(const atom *))); connect(this, SIGNAL(atomInserted(const atomicNumber_t)), worldscene, SLOT(atomInserted(const atomicNumber_t))); connect(this, SIGNAL(atomRemoved(const atomicNumber_t)), worldscene, SLOT(atomRemoved(const atomicNumber_t))); connect(this, SIGNAL(worldSelectionChanged()), worldscene, SLOT(worldSelectionChanged())); connect(this, SIGNAL(moleculeRemoved(const molecule *)), worldscene, SLOT(moleculeRemoved(const molecule *))); //connect(this, SIGNAL(moleculeInserted(const molecule *)), worldscene, SLOT(moleculeInserted(const molecule *))); //connect(this, SIGNAL(changed()), this, SLOT(updateGL())); connect(this, SIGNAL(changed()), this, SLOT(sceneChangeSignalled())); // sign on to changes in the world World::getInstance().signOn(this); World::getInstance().signOn(this, World::AtomInserted); World::getInstance().signOn(this, World::AtomRemoved); World::getInstance().signOn(this, World::MoleculeInserted); World::getInstance().signOn(this, World::MoleculeRemoved); World::getInstance().signOn(this, World::SelectionChanged); WorldTime::getInstance().signOn(this, WorldTime::TimeChanged); AtomObserver::getInstance().signOn(this, AtomObservable::PositionChanged); ShapeRegistry::getInstance().signOn(this); ShapeRegistry::getInstance().signOn(this, ShapeRegistry::ShapeInserted); ShapeRegistry::getInstance().signOn(this, ShapeRegistry::ShapeRemoved); ShapeRegistry::getInstance().signOn(this, ShapeRegistry::SelectionChanged); redrawTimer = new QTimer(this); } GLWorldView::~GLWorldView() { QSettings settings; settings.beginGroup("WorldView"); settings.setValue("domainBoxEnabled", (meshDomainBox->options() & QGLSceneNode::HideNode) == 0); settings.setValue("dreiBeinEnabled", (meshDreiBein->options() & QGLSceneNode::HideNode) == 0); settings.endGroup(); World::getInstance().signOff(this); World::getInstance().signOff(this, World::AtomInserted); World::getInstance().signOff(this, World::AtomRemoved); World::getInstance().signOff(this, World::MoleculeInserted); World::getInstance().signOff(this, World::MoleculeRemoved); World::getInstance().signOff(this, World::SelectionChanged); WorldTime::getInstance().signOff(this, WorldTime::TimeChanged); AtomObserver::getInstance().signOff(this, AtomObservable::PositionChanged); ShapeRegistry::getInstance().signOff(this); ShapeRegistry::getInstance().signOff(this, ShapeRegistry::ShapeInserted); ShapeRegistry::getInstance().signOff(this, ShapeRegistry::ShapeRemoved); ShapeRegistry::getInstance().signOff(this, ShapeRegistry::SelectionChanged); delete worldscene; delete(domainBoxMaterial); for (int i=0;i<3;i++) delete(dreiBeinMaterial[i]); } /** * Add some widget specific actions to the toolbar: * - camera rotation/translation mode * - camera fit to domain */ void GLWorldView::addToolBarActions(QToolBar *toolbar) { // camera control mode toolbar->addSeparator(); QAction *transAction = new QAction(QIcon::fromTheme("forward"), tr("camera translation mode"), this); connect(transAction, SIGNAL(triggered()), this, SLOT(setCameraControlModeTranslation())); toolbar->addAction(transAction); QAction *rotAction = new QAction(QIcon::fromTheme("object-rotate-left"), tr("camera rotation mode"), this); connect(rotAction, SIGNAL(triggered()), this, SLOT(setCameraControlModeRotation())); toolbar->addAction(rotAction); QAction *fitAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("camera fit to domain"), this); connect(fitAction, SIGNAL(triggered()), this, SLOT(fitCameraToDomain())); toolbar->addAction(fitAction); // stereo mode QToolButton *stereoButton = new QToolButton(toolbar); QMenu *stereoMenu = new QMenu(); QAction *stereoDisableAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("disable"), this); connect(stereoDisableAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeDisable())); stereoMenu->addAction(stereoDisableAction); QAction *stereoHardwareAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("hardware"), this); connect(stereoHardwareAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeHardware())); stereoMenu->addAction(stereoHardwareAction); QAction *stereoLeftRightAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("left right"), this); connect(stereoLeftRightAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeLeftRight())); stereoMenu->addAction(stereoLeftRightAction); QAction *stereoRightLeftAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("right left"), this); connect(stereoRightLeftAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeRightLeft())); stereoMenu->addAction(stereoRightLeftAction); QAction *stereoTopBottomAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("top bottom"), this); connect(stereoTopBottomAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeTopBottom())); stereoMenu->addAction(stereoTopBottomAction); QAction *stereoBottomTopAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("bottom top"), this); connect(stereoBottomTopAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeBottomTop())); stereoMenu->addAction(stereoBottomTopAction); QAction *stereoAnaglyphAction = new QAction(QIcon::fromTheme("zoom-best-fit"), tr("anaglyph"), this); connect(stereoAnaglyphAction, SIGNAL(triggered()), this, SLOT(setCameraStereoModeAnaglyph())); stereoMenu->addAction(stereoAnaglyphAction); stereoButton->setMenu(stereoMenu); stereoButton->setIcon(QIcon(QPixmap(":/icon_view_stereo.png"))); stereoButton->setPopupMode(QToolButton::InstantPopup); toolbar->addWidget(stereoButton); // selection mode toolbar->addSeparator(); QAction *selAtomAction = new QAction(QIcon(QPixmap(":/icon_select_atom.png")), tr("select atom by clicking"), this); connect(selAtomAction, SIGNAL(triggered()), worldscene, SLOT(setSelectionModeAtom())); toolbar->addAction(selAtomAction); QAction *selMolAction = new QAction(QIcon(QPixmap(":/icon_select_molecule.png")), tr("select molecule by clicking"), this); connect(selMolAction, SIGNAL(triggered()), worldscene, SLOT(setSelectionModeMolecule())); toolbar->addAction(selMolAction); // dreiBein/domain enabler toolbar->addSeparator(); QAction *seldreiBein = new QAction(QIcon(QPixmap(":/icon_dreiBein.png")), tr("enable/disable dreiBein"), this); connect(seldreiBein, SIGNAL(triggered()), this, SLOT(changeDreiBein())); toolbar->addAction(seldreiBein); QAction *seldomain = new QAction(QIcon(QPixmap(":/icon_domain.png")), tr("enable/disable domain box"), this); connect(seldomain, SIGNAL(triggered()), this, SLOT(changeDomain())); toolbar->addAction(seldomain); } void GLWorldView::createDomainBox() { QSettings settings; settings.beginGroup("WorldView"); QColor colorFrame = settings.value("domainBoxColorFrame", QColor(150,160,200,255)).value(); QColor colorAmbient = settings.value("domainBoxColorAmbient", QColor(50,60,100,255)).value(); QColor colorDiffuse = settings.value("domainBoxColorDiffuse", QColor(150,160,200,180)).value(); settings.setValue("domainBoxColorFrame", colorFrame); settings.setValue("domainBoxColorAmbient", colorAmbient); settings.setValue("domainBoxColorDiffuse", colorDiffuse); const bool status = settings.value("domainBoxEnabled").toBool(); settings.endGroup(); domainBoxMaterial = new QGLMaterial; domainBoxMaterial->setAmbientColor(QColor(0,0,0,255)); domainBoxMaterial->setDiffuseColor(QColor(0,0,0,255)); domainBoxMaterial->setEmittedLight(colorFrame); QGLMaterial *material = new QGLMaterial; material->setAmbientColor(colorAmbient); material->setDiffuseColor(colorDiffuse); QGLBuilder builder; builder << QGL::Faceted; builder << QGLCube(-1.0); // "inverted" => inside faces are used as front. meshDomainBox = builder.finalizedSceneNode(); QMatrix4x4 mat; mat.translate(0.5f, 0.5f, 0.5f); meshDomainBox->setLocalTransform(mat); meshDomainBox->setMaterial(material); setDomainStatus( status ); } void GLWorldView::createDreiBein() { QSettings settings; settings.beginGroup("WorldView"); QColor colorX = settings.value("dreiBeinColorX", QColor(255,50,50,255)).value(); QColor colorY = settings.value("dreiBeinColorY", QColor(50,255,50,255)).value(); QColor colorZ = settings.value("dreiBeinColorZ", QColor(50,50,255,255)).value(); settings.setValue("dreiBeinColorX", colorX); settings.setValue("dreiBeinColorY", colorY); settings.setValue("dreiBeinColorZ", colorZ); const bool status = settings.value("dreiBeinEnabled").toBool(); settings.endGroup(); // Create 3 color for the 3 axes. dreiBeinMaterial[0] = new QGLMaterial; dreiBeinMaterial[0]->setColor(colorX); dreiBeinMaterial[1] = new QGLMaterial; dreiBeinMaterial[1]->setColor(colorY); dreiBeinMaterial[2] = new QGLMaterial; dreiBeinMaterial[2]->setColor(colorZ); // Create the basic meshes (cylinder and cone). QGLBuilder builderCyl; builderCyl << QGLCylinder(.15,.15,1.6,16); QGLSceneNode *cyl = builderCyl.finalizedSceneNode(); QGLBuilder builderCone; builderCone << QGLCylinder(0,.4,0.4,16); QGLSceneNode *cone = builderCone.finalizedSceneNode(); { QMatrix4x4 mat; mat.translate(0.0f, 0.0f, 1.0f); cone->setLocalTransform(mat); } // Create a scene node from the 3 axes. meshDreiBein = new QGLSceneNode(this); // X-direction QGLSceneNode *node = new QGLSceneNode(meshDreiBein); node->setMaterial(dreiBeinMaterial[0]); node->addNode(cyl); node->setPosition(QVector3D(.8f, 0.f, 0.f)); node->addNode(cone); { QMatrix4x4 mat; mat.rotate(90, 0.0f, 1.0f, 0.0f); node->setLocalTransform(mat); } // Y-direction node = new QGLSceneNode(meshDreiBein); node->setMaterial(dreiBeinMaterial[1]); node->addNode(cyl); node->addNode(cone); { QMatrix4x4 mat; mat.rotate(-90, 1.0f, 0.0f, 0.0f); node->setLocalTransform(mat); } node->setPosition(QVector3D(0.f, .8f, 0.f)); // Z-direction node = new QGLSceneNode(meshDreiBein); node->setMaterial(dreiBeinMaterial[2]); node->addNode(cyl); node->addNode(cone); node->setPosition(QVector3D(0.f, 0.f, .8f)); setdreiBeinStatus( status ); } /** * Update operation which can be invoked by the observable (which should be the * change tracker here). */ void GLWorldView::update(Observable *publisher) { emit changed(); } /** * The observable can tell when it dies. */ void GLWorldView::subjectKilled(Observable *publisher) {} /** Listen to specific changes to the world. * * @param publisher ref to observable. * @param notification type of notification */ void GLWorldView::recieveNotification(Observable *publisher, Notification_ptr notification) { if (static_cast(publisher) == World::getPointer()) { switch (notification->getChannelNo()) { case World::AtomInserted: { const atomicNumber_t _id = World::getInstance().lastChanged()->getId(); #ifdef LOG_OBSERVER observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast(this)) << " received notification that atom "+toString(_id)+" has been inserted."; #endif emit atomInserted(_id); break; } case World::AtomRemoved: { const atomicNumber_t _id = World::getInstance().lastChanged()->getId(); #ifdef LOG_OBSERVER observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast(this)) << " received notification that atom "+toString(_id)+" has been removed."; #endif emit atomRemoved(_id); break; } case World::SelectionChanged: { #ifdef LOG_OBSERVER observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast(this)) << " received notification that selection has changed."; #endif emit worldSelectionChanged(); break; } case World::MoleculeInserted: { const molecule *_molecule = World::getInstance().lastChanged(); #ifdef LOG_OBSERVER observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast(this)) << " received notification that molecule "+toString(_molecule->getId())+" has been removed."; #endif emit moleculeInserted(_molecule); break; } case World::MoleculeRemoved: { const molecule *_molecule = World::getInstance().lastChanged(); #ifdef LOG_OBSERVER observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast(this)) << " received notification that molecule "+toString(_molecule->getId())+" has been removed."; #endif emit moleculeRemoved(_molecule); break; } default: ASSERT(0, "GLWorldView::recieveNotification() - we cannot get here for World."); break; } } else if (static_cast(publisher) == WorldTime::getPointer()) { switch (notification->getChannelNo()) { case WorldTime::TimeChanged: { #ifdef LOG_OBSERVER observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast(this)) << " received notification that WorldTime's time has changed."; #endif emit changed(); emit TimeChanged(); break; } default: ASSERT(0, "GLWorldView::recieveNotification() - we cannot get here for WorldTime."); break; } } else if (dynamic_cast(publisher) != NULL) { switch (notification->getChannelNo()) { case AtomObservable::PositionChanged: { #ifdef LOG_OBSERVER const atom *_atom = dynamic_cast(publisher); observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast(this)) << " received notification that atom "+toString(_atom->getId())+" has changed its position."; #endif emit changed(); break; } default: ASSERT(0, "GLWorldView::recieveNotification() - we cannot get here for AtomObservable."); break; } } else if (static_cast(publisher) == ShapeRegistry::getPointer()) { switch (notification->getChannelNo()) { case ShapeRegistry::ShapeInserted: { emit ShapeAdded(); break; } case ShapeRegistry::ShapeRemoved: { emit ShapeRemoved(); break; } case ShapeRegistry::SelectionChanged: { worldscene->updateSelectedShapes(); break; } default: ASSERT(0, "GLWorldView::recieveNotification() - we cannot get here for ShapeRegistry."); break; } } else ASSERT(0, "GLWorldView::recieveNotification() - received notification from unknown source."); } void GLWorldView::checkChanges() { updateGL(); needsRedraw = false; } void GLWorldView::changeDreiBein() { // invert to new status const bool status = ((meshDreiBein->options() & QGLSceneNode::HideNode) == 0); setdreiBeinStatus(!status); // realize updateGL(); needsRedraw = true; } void GLWorldView::setdreiBeinStatus(const bool status) { if (status) meshDreiBein->setOptions( meshDreiBein->options() & (255-QGLSceneNode::HideNode) ); else meshDreiBein->setOptions( meshDreiBein->options() | QGLSceneNode::HideNode ); } void GLWorldView::changeDomain() { // invert to new status const bool status = ((meshDomainBox->options() & QGLSceneNode::HideNode) == 0); setDomainStatus(!status); // realize updateGL(); needsRedraw = true; } void GLWorldView::setDomainStatus(const bool status) { if (status) meshDomainBox->setOptions( meshDomainBox->options() & (255-QGLSceneNode::HideNode) ); else meshDomainBox->setOptions( meshDomainBox->options() | QGLSceneNode::HideNode ); } void GLWorldView::sceneChangeSignalled() { if (!needsRedraw){ redrawTimer->singleShot(0, this, SLOT(checkChanges())); needsRedraw = true; redrawTimer->start(); } } void GLWorldView::initializeGL(QGLPainter *painter) { worldscene->initialize(this, painter); changesPresent = false; } void GLWorldView::paintGL(QGLPainter *painter) { if (changesPresent) { initializeGL(painter); changesPresent = false; } QVector3D cameraDir = camera()->center() - camera()->eye(); cameraDir.normalize(); QVector4D cameraPlane(cameraDir, QVector3D::dotProduct(cameraDir, camera()->eye())); worldscene->draw(painter, cameraPlane); drawDreiBein(painter); // Domain box has to be last because of its transparency. drawDomainBox(painter); } void GLWorldView::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Tab) { // The Tab key turns the ShowPicking option on and off, // which helps show what the pick buffer looks like. setOption(QGLView::ShowPicking, ((options() & QGLView::ShowPicking) == 0)); updateGL(); } QGLView::keyPressEvent(e); } void GLWorldView::changeSignalled() { changesPresent = true; } /** * Set the current camera control mode. */ void GLWorldView::setCameraControlMode(GLWorldView::CameraControlModeType mode) { cameraControlMode = mode; } void GLWorldView::setCameraControlModeRotation() { setCameraControlMode(Rotate); } void GLWorldView::setCameraControlModeTranslation() { setCameraControlMode(Translate); } /** * Returns the current camera control mode. * This needs to be invertable (rotation - translation), if the shift key is pressed. */ GLWorldView::CameraControlModeType GLWorldView::getCameraControlMode(bool inverted) { if (inverted){ if (cameraControlMode == Rotate) return Translate; if (cameraControlMode == Translate) return Rotate; return Rotate; }else return cameraControlMode; } /** * Set the camera so it can oversee the whole domain. */ void GLWorldView::fitCameraToDomain() { // Move the camera focus point to the center of the domain box. Vector v = World::getInstance().getDomain().translateIn(Vector(0.5, 0.5, 0.5)); camera()->setCenter(QVector3D(v[0], v[1], v[2])); // Guess some eye distance. double dist = v.Norm() * 3; camera()->setEye(QVector3D(v[0], v[1], v[2] + dist)); camera()->setUpVector(QVector3D(0, 1, 0)); } void GLWorldView::setCameraStereoModeDisable() { setStereoType(QGLView::Hardware); camera()->setEyeSeparation(0.0); updateGL(); } void GLWorldView::setCameraStereoModeHardware() { setStereoType(QGLView::Hardware); camera()->setEyeSeparation(defaultEyeSeparation); updateGL(); } void GLWorldView::setCameraStereoModeLeftRight() { setStereoType(QGLView::LeftRight); camera()->setEyeSeparation(defaultEyeSeparation); updateGL(); } void GLWorldView::setCameraStereoModeRightLeft() { setStereoType(QGLView::RightLeft); camera()->setEyeSeparation(defaultEyeSeparation); updateGL(); } void GLWorldView::setCameraStereoModeTopBottom() { setStereoType(QGLView::TopBottom); camera()->setEyeSeparation(defaultEyeSeparation); updateGL(); } void GLWorldView::setCameraStereoModeBottomTop() { setStereoType(QGLView::BottomTop); camera()->setEyeSeparation(defaultEyeSeparation); updateGL(); } void GLWorldView::setCameraStereoModeAnaglyph() { setStereoType(QGLView::RedCyanAnaglyph); camera()->setEyeSeparation(defaultEyeSeparation); updateGL(); } void GLWorldView::mousePressEvent(QMouseEvent *event) { QGLView::mousePressEvent(event); // Reset the saved mouse position. lastMousePos = event->posF(); } /** * Handle a mouse move event. * This is used to control the camera (rotation and translation) when the left button is being pressed. */ void GLWorldView::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton){ // Find the mouse distance since the last event. QPointF d = event->posF() - lastMousePos; lastMousePos = event->posF(); // Rotate or translate? (inverted by shift key) CameraControlModeType mode = getCameraControlMode(event->modifiers() & Qt::ShiftModifier); if (mode == Rotate){ // Rotate the camera. d *= 0.3; camera()->tiltPanRollCenter(- d.y(), - d.x(), 0); }else if (mode == Translate){ // Translate the camera. d *= 0.02; camera()->translateCenter(- d.x(), d.y(), 0); camera()->translateEye(- d.x(), d.y(), 0); } }else{ // Without this Qt would not test for hover events (i.e. mouse over an atom). QGLView::mouseMoveEvent(event); } } /** * When the mouse wheel is used, zoom in or out. */ void GLWorldView::wheelEvent(QWheelEvent *event) { // Find the distance between the eye and focus point. QVector3D d = camera()->eye() - camera()->center(); // Scale the distance. if (event->delta() < 0) d *= 1.2; else if (event->delta() > 0) d /= 1.2; // Set new eye position. camera()->setEye(camera()->center() + d); } /** * Draw a transparent cube representing the domain. */ void GLWorldView::drawDomainBox(QGLPainter *painter) const { // Apply the domain matrix. RealSpaceMatrix m = World::getInstance().getDomain().getM(); painter->modelViewMatrix().push(); painter->modelViewMatrix() *= QMatrix4x4(m.at(0,0), m.at(0,1), m.at(0,2), 0.0, m.at(1,0), m.at(1,1), m.at(1,2), 0.0, m.at(2,0), m.at(2,1), m.at(2,2), 0.0, 0.0, 0.0, 0.0, 1.0); // Draw the transparent cube. painter->setStandardEffect(QGL::LitMaterial); glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glEnable(GL_BLEND); glDepthMask(0); //glDisable(GL_DEPTH_TEST); meshDomainBox->draw(painter); //glEnable(GL_DEPTH_TEST); glDepthMask(1); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); // Draw the outlines (if we have drawn the box itself) if ((meshDomainBox->options() & QGLSceneNode::HideNode) == 0) { painter->setFaceMaterial(QGL::AllFaces, domainBoxMaterial); //glEnable(GL_LINE_SMOOTH); QVector3DArray array; array.append(0, 0, 0); array.append(1, 0, 0); array.append(1, 0, 0); array.append(1, 1, 0); array.append(1, 1, 0); array.append(0, 1, 0); array.append(0, 1, 0); array.append(0, 0, 0); array.append(0, 0, 1); array.append(1, 0, 1); array.append(1, 0, 1); array.append(1, 1, 1); array.append(1, 1, 1); array.append(0, 1, 1); array.append(0, 1, 1); array.append(0, 0, 1); array.append(0, 0, 0); array.append(0, 0, 1); array.append(1, 0, 0); array.append(1, 0, 1); array.append(0, 1, 0); array.append(0, 1, 1); array.append(1, 1, 0); array.append(1, 1, 1); painter->clearAttributes(); painter->setVertexAttribute(QGL::Position, array); painter->draw(QGL::Lines, 24); } painter->modelViewMatrix().pop(); } void GLWorldView::drawDreiBein(QGLPainter *painter) { painter->modelViewMatrix().push(); painter->modelViewMatrix().translate(camera()->center()); painter->setStandardEffect(QGL::LitMaterial); painter->setFaceMaterial(QGL::FrontFaces, NULL); meshDreiBein->draw(painter); painter->modelViewMatrix().pop(); } void GLWorldView::sceneHoverSignalled(const atom *_atom) { emit hoverChanged(_atom); } //#include //#include //#include // //#include "ui_dialoglight.h" // //#include "CodePatterns/MemDebug.hpp" // //#include //#include // //#include "LinearAlgebra/Line.hpp" //#include "Atom/atom.hpp" //#include "Bond/bond.hpp" //#include "Element/element.hpp" //#include "molecule.hpp" //#include "Element/periodentafel.hpp" //#include "World.hpp" // //#if defined(Q_CC_MSVC) //#pragma warning(disable:4305) // init: truncation from const double to float //#endif // // //GLMoleculeView::GLMoleculeView(QWidget *parent) : // QGLWidget(parent), Observer("GLMoleculeView"), X(Vector(1,0,0)), Y(Vector(0,1,0)), Z(Vector(0,0,1)) //{ // xRot = yRot = zRot = 0.0; // default object rotation // scale = 5.; // default object scale // object = 0; // LightPosition[0] = 0.0f; // LightPosition[1] = 2.0f; // LightPosition[2] = 2.0f; // LightPosition[3] = 0.0f; // LightDiffuse[0] = 0.5f; // LightDiffuse[1] = 0.5f; // LightDiffuse[2] = 0.5f; // LightDiffuse[3] = 0.0f; // LightAmbient[0] = 0.0f; // LightAmbient[1] = 0.0f; // LightAmbient[2] = 0.0f; // LightAmbient[3] = 0.0f; // // SelectionColor[0] = 0; // SelectionColor[1] = 128; // SelectionColor[2] = 128; // // MultiViewEnabled = true; // // isSignaller = false; // // World::getInstance().signOn(this); //} // ///** Destructor of GLMoleculeView. // * Free's the CallList. // */ //GLMoleculeView::~GLMoleculeView() //{ // makeCurrent(); // glDeleteLists( object, 1 ); // // World::getInstance().signOff(this); //} // ///** Paints the conents of the OpenGL window. // * Clears the GL buffers, enables lighting and depth. // * Window is either quartered (if GLMoleculeView::MultiViewEnabled) and xy, xz, yz planar views // * are added. Uses the CallList, constructed during InitializeGL(). // */ //void GLMoleculeView::paintGL() //{ // Vector spot; // // glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // glShadeModel(GL_SMOOTH); // Enable Smooth Shading // glEnable(GL_LIGHTING); // Enable Light One // glEnable(GL_DEPTH_TEST); // Enables Depth Testing // glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do // glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations // // // 3d viewport // if (MultiViewEnabled) // glViewport( 0, 0, (GLint)width/2, (GLint)height/2 ); // else // glViewport( 0, 0, (GLint)width, (GLint)height ); // glMatrixMode( GL_PROJECTION ); // glLoadIdentity(); // glFrustum( -1.0, 1.0, -1.0, 1.0, 1.0, 50.0 ); // glMatrixMode( GL_MODELVIEW ); // glLoadIdentity(); // // // calculate point of view and direction // glTranslated(position[0],position[1],position[2]); // glTranslated(0.0, 0.0, -scale); // glRotated(xRot, 1.0, 0.0, 0.0); // glRotated(yRot, 0.0, 1.0, 0.0); // glRotated(zRot, 0.0, 0.0, 1.0); // // // render scene // glCallList(object); // // // enable light // glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light // glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light // glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light // glEnable(GL_LIGHT1); // Enable Light One // // if (MultiViewEnabled) { // // xy view port // glViewport( (GLint)width/2, 0, (GLint)width/2, (GLint)height/2 ); // glMatrixMode( GL_PROJECTION ); // glLoadIdentity(); // glScalef(1./scale, 1./scale,1./scale); // glOrtho(0, width/2, 0, height/2, 0,0); // glMatrixMode( GL_MODELVIEW ); // glLoadIdentity(); // // // calculate point of view and direction // view = position; // spot = Vector(0.,0.,scale); // top = Vector(0.,1.,0.); // gluLookAt( // spot[0], spot[1], spot[2], // view[0], view[1], view[2], // top[0], top[1], top[2]); // // // enable light // glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light // glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light // glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light // glEnable(GL_LIGHT1); // Enable Light One // // // render scene // glCallList(object); // // // xz viewport // glViewport( 0, (GLint)height/2, (GLint)width/2, (GLint)height/2 ); // glMatrixMode( GL_PROJECTION ); // glLoadIdentity(); // glScalef(1./scale, 1./scale,1./scale); // glOrtho(0, width/2, 0, height/2, 0,0); // glMatrixMode( GL_MODELVIEW ); // glLoadIdentity(); // // // calculate point of view and direction // view = position; // spot = Vector(0.,scale,0.); // top = Vector(1.,0.,0.); // gluLookAt( // spot[0], spot[1], spot[2], // view[0], view[1], view[2], // top[0], top[1], top[2]); // // // enable light // glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light // glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light // glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light // glEnable(GL_LIGHT1); // Enable Light One // // // render scene // glCallList(object); // // //yz viewport // glViewport( (GLint)width/2, (GLint)height/2, (GLint)width/2, (GLint)height/2 ); // glMatrixMode( GL_PROJECTION ); // glLoadIdentity(); // glScalef(1./scale, 1./scale,1./scale); // glOrtho(0, width/2, 0, height/2, 0,0); // glMatrixMode( GL_MODELVIEW ); // glLoadIdentity(); // // // calculate point of view and direction // view= position; // spot = Vector(scale,0.,0.); // top = Vector(0.,1.,0.); // gluLookAt( // spot[0], spot[1], spot[2], // view[0], view[1], view[2], // top[0], top[1], top[2]); // // // enable light // glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light // glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light // glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light // glEnable(GL_LIGHT1); // Enable Light One // // // render scene // glCallList(object); // } // //CoordinatesBar->setText( QString ("X: %1, Y: %2, Z: %3").arg(position[0]).arg(position[1]).arg(position[2]) ); //} // ////void polarView{GLdouble distance, GLdouble twist, //// GLdouble elevation, GLdouble azimuth) ////{ //// glTranslated(0.0, 0.0, -distance); //// glRotated(-twist, 0.0, 0.0, 1.0); //// glRotated(-elevation, 1.0, 0.0, 0.0); //// glRotated(azimuth, 0.0, 0.0, 1.0); ////} // ///** Make a sphere. // * \param x position // * \param radius radius // * \param color[3] color rgb values // */ //void GLMoleculeView::makeSphere(const Vector &x, double radius, const unsigned char color[3]) //{ // 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 // GLUquadricObj* q = gluNewQuadric (); // gluQuadricOrientation(q, GLU_OUTSIDE); // // std::cout << "Setting sphere at " << x << " with color r" // << (int)color[0] << ",g" << (int)color[1] << ",b" << (int)color[2] << "." << endl; // // glPushMatrix(); // glTranslatef( x[0], x[1], x[2]); //// glRotatef( xRot, 1.0, 0.0, 0.0); //// glRotatef( yRot, 0.0, 1.0, 0.0); //// glRotatef( zRot, 0.0, 0.0, 1.0); // glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blueMaterial); // gluSphere (q, (GLdouble)radius, 10, 10); // glPopMatrix(); //} // ///** Make a cylinder. // * \param x origin // * \param y direction // * \param radius thickness // * \param height length // * \color[3] color rgb values // */ //void GLMoleculeView::makeCylinder(const Vector &x, const Vector &y, double radius, double height, const unsigned char color[3]) //{ // float blueMaterial[] = { 255./(float)color[0], 255./(float)color[1], 255./(float)color[2], 1 }; // GLUquadricObj* q = gluNewQuadric (); // gluQuadricOrientation(q, GLU_OUTSIDE); // Vector a,b; // Vector OtherAxis; // double alpha; // a = x - y; // // construct rotation axis // b = a; // b.VectorProduct(Z); // Line axis(zeroVec, b); // // calculate rotation angle // alpha = a.Angle(Z); // // construct other axis to check right-hand rule // OtherAxis = b; // OtherAxis.VectorProduct(Z); // // assure right-hand rule for the rotation // if (a.ScalarProduct(OtherAxis) < MYEPSILON) // alpha = M_PI-alpha; // // check // Vector a_rotated = axis.rotateVector(a, alpha); // std::cout << "Setting cylinder from "// << x << " to " << y // << a << " to " << a_rotated << " around " << b << " by " << alpha/M_PI*180. << ", respectively, " // << " with color r" // << (int)color[0] << ",g" << (int)color[1] << ",b" << (int)color[2] << "." << endl; // // glPushMatrix(); // glTranslatef( x[0], x[1], x[2]); // glRotatef( alpha/M_PI*180., b[0], b[1], b[2]); // glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blueMaterial); // gluCylinder (q, (GLdouble)radius, (GLdouble)radius, (GLdouble)height, 10, 10); // glPopMatrix(); //} // ///** Defines the display CallList. // * Goes through all molecules and their atoms and adds spheres for atoms and cylinders // * for bonds. Heeds GLMoleculeView::SelectedAtom and GLMoleculeView::SelectedMolecule. // */ //void GLMoleculeView::initializeGL() //{ // double x[3] = {-1, 0, -10}; // unsigned char white[3] = {255,255,255}; // Vector Position, OtherPosition; // QSize window = size(); // width = window.width(); // height = window.height(); // std::cout << "Setting width to " << width << " and height to " << height << std::endl; // GLfloat shininess[] = { 0.0 }; // GLfloat specular[] = { 0, 0, 0, 1 }; // glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Let OpenGL clear to black // object = glGenLists(1); // glNewList( object, GL_COMPILE ); // glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); // glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess); // // const std::vector &molecules = World::getInstance().getAllMolecules(); // // if (molecules.size() > 0) { // for (std::vector::const_iterator Runner = molecules.begin(); // Runner != molecules.end(); // Runner++) { // for (molecule::const_iterator atomiter = (*Runner)->begin(); // atomiter != (*Runner)->end(); // ++atomiter) { // // create atom // const element *ptr = (*atomiter)->getType(); // boost::shared_ptr MolCenter((*Runner)->DetermineCenterOfGravity()); // Position = (*atomiter)->getPosition() - *MolCenter; // const unsigned char* color = NULL; // if ((World::getInstance().isSelected(*atomiter)) || (World::getInstance().isSelected((*Runner)))) // color = SelectionColor; // else // color = ptr->getColor(); // makeSphere(Position, ptr->getVanDerWaalsRadius()*0.25, color); // // // create bonds // const BondList &bonds = (*atomiter)->getListOfBonds(); // for (BondList::const_iterator bonditer = bonds.begin(); // bonditer != bonds.end(); // ++bonditer) { // if ((*bonditer)->leftatom->getId() == (*atomiter)->getId()) { // Position = (*bonditer)->leftatom->getPosition() - *MolCenter; // OtherPosition = (*bonditer)->rightatom->getPosition() - *MolCenter; // const double distance = sqrt(Position.DistanceSquared(OtherPosition))/2.; // const unsigned char *color1 = (*bonditer)->leftatom->getType()->getColor(); // const unsigned char *color2 = (*bonditer)->rightatom->getType()->getColor(); // makeCylinder(Position, OtherPosition, 0.1, distance, color1); // makeCylinder(OtherPosition, Position, 0.1, distance, color2); // } // } // } // } // } else { // makeSphere( x,1, white); // } // glEndList(); //} // // ///* ================================== SLOTS ============================== */ // ///** Initializes some public variables. // * \param *ptr pointer to QLabel statusbar // */ //void GLMoleculeView::init(QLabel *ptr) //{ // StatusBar = ptr; //} // ///** Initializes the viewport statusbar. // * \param *ptr pointer to QLabel for showing view pointcoordinates. // */ //void GLMoleculeView::initCoordinates(QLabel *ptr) //{ // CoordinatesBar = ptr; //} // ///** Slot to be called when to initialize GLMoleculeView::MolData. // */ //void GLMoleculeView::createView( ) //{ // initializeGL(); // updateGL(); //} // ///** Slot of window is resized. // * Copies new width and height to GLMoleculeView::width and GLMoleculeView::height and calls updateGL(). // * \param w new width of window // * \param h new height of window // */ //void GLMoleculeView::resizeGL( int w, int h ) //{ // width = w; // height = h; // updateGL(); //} // ///** Sets x rotation angle. // * sets GLMoleculeView::xRot and calls updateGL(). // * \param degrees new rotation angle in degrees // */ //void GLMoleculeView::setXRotation( int degrees ) //{ // xRot = (GLfloat)(degrees % 360); // updateGL(); //} // // ///** Sets y rotation angle. // * sets GLMoleculeView::yRot and calls updateGL(). // * \param degrees new rotation angle in degrees // */ //void GLMoleculeView::setYRotation( int degrees ) //{ // yRot = (GLfloat)(degrees % 360); // updateGL(); //} // // ///** Sets z rotation angle. // * sets GLMoleculeView::zRot and calls updateGL(). // * \param degrees new rotation angle in degrees // */ //void GLMoleculeView::setZRotation( int degrees ) //{ // zRot = (GLfloat)(degrees % 360); // updateGL(); //} // ///** Sets the scale of the scene. // * sets GLMoleculeView::scale and calls updateGL(). // * \param distance distance divided by 100 is the new scale // */ //void GLMoleculeView::setScale( int distance ) //{ // scale = (GLfloat)(distance / 100.); // updateGL(); //} // ///** Update the ambient light. // * \param light[4] light strength per axis and position (w) // */ //void GLMoleculeView::setLightAmbient( int *light ) //{ // for(int i=0;i<4;i++) // LightAmbient[i] = light[i]; // updateGL(); //} // ///** Update the diffuse light. // * \param light[4] light strength per axis and position (w) // */ //void GLMoleculeView::setLightDiffuse( int *light ) //{ // for(int i=0;i<4;i++) // LightDiffuse[i] = light[i]; // updateGL(); //} // ///** Update the position of light. // * \param light[4] light strength per axis and position (w) // */ //void GLMoleculeView::setLightPosition( int *light ) //{ // for(int i=0;i<4;i++) // LightPosition[i] = light[i]; // updateGL(); //} // ///** Toggles the boolean GLMoleculeView::MultiViewEnabled. // * Flips the boolean and calls updateGL(). // */ //void GLMoleculeView::toggleMultiViewEnabled ( ) //{ // MultiViewEnabled = !MultiViewEnabled; // cout << "Setting MultiView to " << MultiViewEnabled << "." << endl; // updateGL(); //} // ///** Launch a dialog to configure the lights. // */ //void GLMoleculeView::createDialogLight() //{ //// Ui_DialogLight *Lights = new Ui_DialogLight(); //// if (Lights == NULL) //// return; //// // Set up the dynamic dialog here //// QLineEdit *Field = NULL; //// Field = Lights->findChild("LightPositionX"); //// if (Field) Field->setText( QString("%1").arg(LightPosition[0]) ); //// Field = Lights->findChild("LightPositionY"); //// if (Field) Field->setText( QString("%1").arg(LightPosition[1]) ); //// Field = Lights->findChild("LightPositionZ"); //// if (Field) Field->setText( QString("%1").arg(LightPosition[2]) ); //// Field = Lights->findChild("LightPositionW"); //// if (Field) Field->setText( QString("%1").arg(LightPosition[3]) ); //// //// Field = Lights->findChild("LightDiffuseX"); //// if (Field) Field->setText( QString("%1").arg(LightDiffuse[0]) ); //// Field = Lights->findChild("LightDiffuseY"); //// if (Field) Field->setText( QString("%1").arg(LightDiffuse[1]) ); //// Field = Lights->findChild("LightDiffuseZ"); //// if (Field) Field->setText( QString("%1").arg(LightDiffuse[2]) ); //// Field = Lights->findChild("LightDiffuseW"); //// if (Field) Field->setText( QString("%1").arg(LightDiffuse[3]) ); //// //// Field = Lights->findChild("LightAmbientX"); //// if (Field) Field->setText( QString("%1").arg(LightAmbient[0]) ); //// Field = Lights->findChild("LightAmbientY"); //// if (Field) Field->setText( QString("%1").arg(LightAmbient[1]) ); //// Field = Lights->findChild("LightAmbientZ"); //// if (Field) Field->setText( QString("%1").arg(LightAmbient[2]) ); //// Field = Lights->findChild("LightAmbientW"); //// if (Field) Field->setText( QString("%1").arg(LightAmbient[3]) ); //// //// if ( Lights->exec() ) { //// //cout << "User accepted.\n"; //// // The user accepted, act accordingly //// Field = Lights->findChild("LightPositionX"); //// if (Field) LightPosition[0] = Field->text().toDouble(); //// Field = Lights->findChild("LightPositionY"); //// if (Field) LightPosition[1] = Field->text().toDouble(); //// Field = Lights->findChild("LightPositionZ"); //// if (Field) LightPosition[2] = Field->text().toDouble(); //// Field = Lights->findChild("LightPositionW"); //// if (Field) LightPosition[3] = Field->text().toDouble(); //// //// Field = Lights->findChild("LightDiffuseX"); //// if (Field) LightDiffuse[0] = Field->text().toDouble(); //// Field = Lights->findChild("LightDiffuseY"); //// if (Field) LightDiffuse[1] = Field->text().toDouble(); //// Field = Lights->findChild("LightDiffuseZ"); //// if (Field) LightDiffuse[2] = Field->text().toDouble(); //// Field = Lights->findChild("LightDiffuseW"); //// if (Field) LightDiffuse[3] = Field->text().toDouble(); //// //// Field = Lights->findChild("LightAmbientX"); //// if (Field) LightAmbient[0] = Field->text().toDouble(); //// Field = Lights->findChild("LightAmbientY"); //// if (Field) LightAmbient[1] = Field->text().toDouble(); //// Field = Lights->findChild("LightAmbientZ"); //// if (Field) LightAmbient[2] = Field->text().toDouble(); //// Field = Lights->findChild("LightAmbientW"); //// if (Field) LightAmbient[3] = Field->text().toDouble(); //// updateGL(); //// } else { //// //cout << "User reclined.\n"; //// } //// delete(Lights); //} // ///** Slot for event of pressed mouse button. // * Switch discerns between buttons and stores position of event in GLMoleculeView::LeftButtonPos, // * GLMoleculeView::MiddleButtonPos or GLMoleculeView::RightButtonPos. // * \param *event structure containing information of the event // */ //void GLMoleculeView::mousePressEvent(QMouseEvent *event) //{ // std::cout << "MousePressEvent." << endl; // QPoint *pos = NULL; // switch (event->button()) { // get the right array // case Qt::LeftButton: // pos = &LeftButtonPos; // std::cout << "Left Button" << endl; // break; // case Qt::MidButton: // pos = &MiddleButtonPos; // std::cout << "Middle Button" << endl; // break; // case Qt::RightButton: // pos = &RightButtonPos; // std::cout << "Right Button" << endl; // break; // default: // break; // } // if (pos) { // store the position // pos->setX(event->pos().x()); // pos->setY(event->pos().y()); // std::cout << "Stored src position is (" << pos->x() << "," << pos->y() << ")." << endl; // } else { // std::cout << "pos is NULL." << endl; // } //} // ///** Slot for event of pressed mouse button. // * Switch discerns between buttons: // * -# Left Button: Rotates the view of the GLMoleculeView, relative to GLMoleculeView::LeftButtonPos. // * -# Middle Button: nothing // * -# Right Button: Shifts the selected molecule or atom, relative to GLMoleculeView::RightButtonPos. // * \param *event structure containing information of the event // */ //void GLMoleculeView::mouseReleaseEvent(QMouseEvent *event) //{ // std::cout << "MouseReleaseEvent." << endl; // QPoint *srcpos = NULL; // QPoint destpos = event->pos(); // int Width = (MultiViewEnabled) ? width/2 : width; // int Height = (MultiViewEnabled) ? height/2 : height; // std::cout << "Received dest position is (" << destpos.x() << "," << destpos.y() << ")." << endl; // switch (event->button()) { // get the right array // case Qt::LeftButton: // LeftButton rotates the view // srcpos = &LeftButtonPos; // std::cout << "Left Button" << endl; // if (srcpos) { // subtract the position and act // std::cout << "Stored src position is (" << srcpos->x() << "," << srcpos->y() << ")." << endl; // destpos -= *srcpos; // std::cout << "Resulting diff position is (" << destpos.x() << "," << destpos.y() << ")." << endl; // std::cout << "Width and Height are " << Width << "," << Height << "." << endl; // // int pos = (int)floor((double)srcpos->x()/(double)Width) + ((int)floor((double)srcpos->y()/(double)Height))*2; // if ((MultiViewEnabled) && (pos != 2)) { // means four regions, and we are in a shifting one // // switch between three regions // // decide into which of the four screens the initial click has been made // std::cout << "Position is " << pos << "." << endl; // switch(pos) { // case 0: // lower left = xz // position[0] += -destpos.y()/100.; // position[2] += destpos.x()/100.; // break; // case 1: // lower right = yz // position[1] += -destpos.y()/100.; // position[2] += -destpos.x()/100.; // break; // case 2: // upper left = projected // std::cout << "This is impossible: Shifting in the projected region, we should rotate!." << endl; // break; // case 3: // upper right = xy // position[0] += destpos.x()/100.; // position[1] += -destpos.y()/100.; // break; // default: // std::cout << "click was not in any of the four regions." << endl; // break; // } // updateGL(); // } else { // we are in rotation region // QWidget *Parent = parentWidget(); // QSlider *sliderX = Parent->findChild("sliderX"); // QSlider *sliderY = Parent->findChild("sliderY"); // std::cout << sliderX << " and " << sliderY << endl; // if (sliderX) { // int xrange = sliderX->maximum() - sliderX->minimum(); // double xValue = ((destpos.x() + Width) % Width); // xValue *= (double)xrange/(double)Width; // xValue += sliderX->value(); // int xvalue = (int) xValue % xrange; // std::cout << "Setting x to " << xvalue << " within range " << xrange << "." << endl; // setXRotation(xvalue); // sliderX->setValue(xvalue); // } else { // std::cout << "sliderX is NULL." << endl; // } // if (sliderY) { // int yrange = sliderY->maximum() - sliderY->minimum(); // double yValue = ((destpos.y() + Height) % Height); // yValue *= (double)yrange/(double)Height; // yValue += sliderY->value(); // int yvalue = (int) yValue % yrange; // std::cout << "Setting y to " << yvalue << " within range " << yrange << "." << endl; // setYRotation(yvalue); // sliderY->setValue(yvalue); // } else { // std::cout << "sliderY is NULL." << endl; // } // } // } else { // std::cout << "srcpos is NULL." << endl; // } // break; // // case Qt::MidButton: // MiddleButton has no function so far // srcpos = &MiddleButtonPos; // std::cout << "Middle Button" << endl; // if (srcpos) { // subtract the position and act // QWidget *Parent = parentWidget(); // QSlider *sliderZ = Parent->findChild("sliderZ"); // QSlider *sliderScale = Parent->findChild("sliderScale"); // std::cout << sliderZ << " and " << sliderScale << endl; // std::cout << "Stored src position is (" << srcpos->x() << "," << srcpos->y() << ")." << endl; // destpos -= *srcpos; // std::cout << "Resulting diff position is (" << destpos.x() << "," << destpos.y() << ")." << endl; // std::cout << "Width and Height are " << Width << "," << Height << "." << endl; // if (sliderZ) { // int xrange = sliderZ->maximum() - sliderZ->minimum(); // double xValue = ((destpos.x() + Width) % Width); // xValue *= (double)xrange/(double)Width; // xValue += sliderZ->value(); // int xvalue = (int) xValue % xrange; // std::cout << "Setting x to " << xvalue << " within range " << xrange << "." << endl; // setZRotation(xvalue); // sliderZ->setValue(xvalue); // } else { // std::cout << "sliderZ is NULL." << endl; // } // if (sliderScale) { // int yrange = sliderScale->maximum() - sliderScale->minimum(); // double yValue = ((destpos.y() + Height) % Height); // yValue *= (double)yrange/(double)Height; // yValue += sliderScale->value(); // int yvalue = (int) yValue % yrange; // std::cout << "Setting y to " << yvalue << " within range " << yrange << "." << endl; // setScale(yvalue); // sliderScale->setValue(yvalue); // } else { // std::cout << "sliderScale is NULL." << endl; // } // } else { // std::cout << "srcpos is NULL." << endl; // } // break; // break; // // case Qt::RightButton: // RightButton moves eitstdher the selected molecule or atom // srcpos = &RightButtonPos; // std::cout << "Right Button" << endl; // if (srcpos) { // subtract the position and act // std::cout << "Stored src position is (" << srcpos->x() << "," << srcpos->y() << ")." << endl; // destpos -= *srcpos; // std::cout << "Resulting diff position is (" << destpos.x() << "," << destpos.y() << ")." << endl; // std::cout << "Width and Height are " << Width << "," << Height << "." << endl; // if (MultiViewEnabled) { // // which vector to change // Vector SelectedPosition; // const std::vector &SelectedAtoms = World::getInstance().getSelectedAtoms(); // const std::vector &SelectedMolecules = World::getInstance().getSelectedMolecules(); // if (SelectedMolecules.size()) { // if (SelectedAtoms.size()) // SelectedPosition = (*SelectedAtoms.begin())->getPosition(); // else // SelectedPosition = (*(*SelectedMolecules.begin())->begin())->getPosition(); // } // // decide into which of the four screens the initial click has been made // int pos = (int)floor((double)srcpos->x()/(double)Width) + ((int)floor((double)srcpos->y()/(double)Height))*2; // if (!SelectedPosition.IsZero()) { // std::cout << "Position is " << pos << "." << endl; // switch(pos) { // case 0: // lower left = xz // SelectedPosition[0] += -destpos.y()/100.; // SelectedPosition[2] += destpos.x()/100.; // break; // case 1: // lower right = yz // SelectedPosition[1] += -destpos.y()/100.; // SelectedPosition[2] += -destpos.x()/100.; // break; // case 2: // upper left = projected // SelectedPosition[0] += destpos.x()/100.; // SelectedPosition[1] += destpos.y()/100.; // SelectedPosition[2] += destpos.y()/100.; // break; // case 3: // upper right = xy // SelectedPosition[0] += destpos.x()/100.; // SelectedPosition[1] += -destpos.y()/100.; // break; // default: // std::cout << "click was not in any of the four regions." << endl; // break; // } // } else { // std::cout << "Nothing selected." << endl; // } // // update Tables // if (SelectedMolecules.size()) { // isSignaller = true; // if (SelectedAtoms.size()) // emit notifyAtomChanged( (*SelectedMolecules.begin()), (*SelectedAtoms.begin()), AtomPosition); // else // emit notifyMoleculeChanged( (*SelectedMolecules.begin()), MoleculePosition ); // } // // update graphic // initializeGL(); // updateGL(); // } else { // cout << "MultiView is not enabled." << endl; // } // } else { // cout << "srcpos is NULL." << endl; // } // break; // // default: // break; // } //} // ///* ======================================== SLOTS ================================ */ // ///** Hear announcement of selected molecule. // * \param *mol pointer to selected molecule // */ //void GLMoleculeView::hearMoleculeSelected(molecule *mol) //{ // if (isSignaller) { // if we emitted the signal, return // isSignaller = false; // return; // } // initializeGL(); // updateGL(); //}; // ///** Hear announcement of selected atom. // * \param *mol pointer to molecule containing atom // * \param *Walker pointer to selected atom // */ //void GLMoleculeView::hearAtomSelected(molecule *mol, atom *Walker) //{ // if (isSignaller) { // if we emitted the signal, return // isSignaller = false; // return; // } // initializeGL(); // updateGL(); //}; // ///** Hear announcement of changed molecule. // * \param *mol pointer to changed molecule // * \param type of change // */ //void GLMoleculeView::hearMoleculeChanged(molecule *mol, enum ChangesinMolecule type) //{ // if (isSignaller) { // if we emitted the signal, return // isSignaller = false; // return; // } // initializeGL(); // updateGL(); //}; // ///** Hear announcement of changed atom. // * \param *mol pointer to molecule containing atom // * \param *Walker pointer to changed atom // * \param type type of change // */ //void GLMoleculeView::hearAtomChanged(molecule *mol, atom *Walker, enum ChangesinAtom type) //{ // if (isSignaller) { // if we emitted the signal, return // isSignaller = false; // return; // } // initializeGL(); // updateGL(); //}; // ///** Hear announcement of changed element. // * \param *Runner pointer to changed element // * \param type of change // */ //void GLMoleculeView::hearElementChanged(element *Runner, enum ChangesinElement type) //{ // if (isSignaller) { // if we emitted the signal, return // isSignaller = false; // return; // } // switch(type) { // default: // case ElementName: // case ElementSymbol: // case ElementMass: // case ElementValence: // case ElementZ: // break; // case ElementCovalent: // case ElementVanderWaals: // initializeGL(); // updateGL(); // break; // } //}; // ///** Hear announcement of added molecule. // * \param *mol pointer to added molecule // */ //void GLMoleculeView::hearMoleculeAdded(molecule *mol) //{ // if (isSignaller) { // if we emitted the signal, return // isSignaller = false; // return; // } // initializeGL(); // updateGL(); //}; // ///** Hear announcement of added atom. // * \param *mol pointer to molecule containing atom // * \param *Walker pointer to added atom // */ //void GLMoleculeView::hearAtomAdded(molecule *mol, atom *Walker) //{ // if (isSignaller) { // if we emitted the signal, return // isSignaller = false; // return; // } // initializeGL(); // updateGL(); //}; // ///** Hear announcement of removed molecule. // * \param *mol pointer to removed molecule // */ //void GLMoleculeView::hearMoleculeRemoved(molecule *mol) //{ // if (isSignaller) { // if we emitted the signal, return // isSignaller = false; // return; // } // initializeGL(); // updateGL(); //}; // ///** Hear announcement of removed atom. // * \param *mol pointer to molecule containing atom // * \param *Walker pointer to removed atom // */ //void GLMoleculeView::hearAtomRemoved(molecule *mol, atom *Walker) //{ // if (isSignaller) { // if we emitted the signal, return // isSignaller = false; // return; // } // initializeGL(); // updateGL(); //}; // //void GLMoleculeView::update(Observable *publisher) //{ // initializeGL(); // updateGL(); //} // ///** // * This method is called when a special named change // * of the Observable occured // */ //void GLMoleculeView::recieveNotification(Observable *publisher, Notification_ptr notification) //{ // initializeGL(); // updateGL(); //} // ///** // * This method is called when the observed object is destroyed. // */ //void GLMoleculeView::subjectKilled(Observable *publisher) //{ // //} // // //// new stuff // ///** Returns the ref to the Material for element No \a from the map. // * // * \note We create a new one if the element is missing. // * // * @param no element no // * @return ref to QGLMaterial // */ //QGLMaterial* GLMoleculeView::getMaterial(size_t no) //{ // if (ElementNoMaterialMap.find(no) != ElementNoMaterialMap.end()){ // // get present one // // } else { // ASSERT( (no >= 0) && (no < MAX_ELEMENTS), // "GLMoleculeView::getMaterial() - Element no "+toString(no)+" is invalid."); // // create new one // LOG(1, "Creating new material for element "+toString(no)+"."); // QGLMaterial *newmaterial = new QGLMaterial(this); // periodentafel *periode = World::getInstance().getPeriode(); // element *desiredelement = periode->FindElement(no); // ASSERT(desiredelement != NULL, // "GLMoleculeView::getMaterial() - desired element "+toString(no)+" not present in periodentafel."); // const unsigned char* color = desiredelement->getColor(); // newmaterial->setAmbientColor( QColor(color[0], color[1], color[2]) ); // newmaterial->setSpecularColor( QColor(60, 60, 60) ); // newmaterial->setShininess( QColor(128) ); // ElementNoMaterialMap.insert( no, newmaterial); // } //} // //QGLSceneNode* GLMoleculeView::getAtom(size_t no) //{ // // first some sensibility checks // ASSERT(World::getInstance().getAtom(AtomById(no)) != NULL, // "GLMoleculeView::getAtom() - desired atom " // +toString(no)+" not present in the World."); // ASSERT(AtomsinSceneMap.find(no) != AtomsinSceneMap.end(), // "GLMoleculeView::getAtom() - desired atom " // +toString(no)+" not present in the AtomsinSceneMap."); // // return AtomsinSceneMap[no]; //} // //QGLSceneNode* GLMoleculeView::getBond(size_t leftno, size_t rightno) //{ // // first some sensibility checks // ASSERT(World::getInstance().getAtom(AtomById(leftno)) != NULL, // "GLMoleculeView::getAtom() - desired atom " // +toString(leftno)+" of bond not present in the World."); // ASSERT(World::getInstance().getAtom(AtomById(rightno)) != NULL, // "GLMoleculeView::getAtom() - desired atom " // +toString(rightno)+" of bond not present in the World."); // ASSERT(AtomsinSceneMap.find(leftno) != AtomsinSceneMap.end(), // "GLMoleculeView::getAtom() - desired atom " // +toString(leftno)+" of bond not present in the AtomsinSceneMap."); // ASSERT(AtomsinSceneMap.find(rightno) != AtomsinSceneMap.end(), // "GLMoleculeView::getAtom() - desired atom " // +toString(rightno)+" of bond not present in the AtomsinSceneMap."); // ASSERT(leftno == rightno, // "GLMoleculeView::getAtom() - bond must not be between the same atom: " // +toString(leftno)+" == "+toString(rightno)+"."); // // // then return with smaller index first // if (leftno > rightno) // return AtomsinSceneMap[ make_pair(rightno, leftno) ]; // else // return AtomsinSceneMap[ make_pair(leftno, rightno) ]; //} //