/*
* 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) ];
//}
//