/*
* 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 "Descriptors/MoleculeIdDescriptor.hpp"
#include "molecule.hpp"
#include "Shapes/ShapeRegistry.hpp"
#include "World.hpp"
#include "WorldTime.hpp"
GLWorldView::GLWorldView(
QtObservedInstanceBoard * _board,
QWidget *parent) :
QGLView(parent),
Observer("GLWorldView"),
worldscene(NULL),
changesPresent(false),
needsRedraw(false)
{
worldscene = new GLWorldScene(_board, this);
setOption(QGLView::ObjectPicking, true);
setOption(QGLView::CameraNavigation, false);
setFocusPolicy(Qt::StrongFocus);
setCameraControlMode(Rotate);
defaultEyeSeparation = 4.0;
createDomainBox();
createDreiBein();
//changeMaterials(false);
qRegisterMetaType("atomId_t");
qRegisterMetaType("moleculeId_t");
connect(this, SIGNAL(ShapeAdded(const std::string &)), worldscene, SLOT(addShape(const std::string &)));
connect(this, SIGNAL(ShapeRemoved(const std::string &)), worldscene, SLOT(removeShape(const std::string &)));
// connect(this, SIGNAL(TimeChanged()), worldscene, SIGNAL(updated()));
connect(worldscene, SIGNAL(changeOccured()), this, SLOT(changeSignalled()));
connect(this, SIGNAL(changed()), this, SLOT(changeSignalled()));
connect(worldscene, SIGNAL(hoverChanged(const atomId_t)), this, SLOT(sceneHoverSignalled(const atomId_t)));
connect(worldscene, SIGNAL(hoverChanged(const moleculeId_t, int)), this, SLOT(sceneHoverSignalled(const moleculeId_t, int)));
//connect(this, SIGNAL(changed()), this, SLOT(updateGL()));
connect(worldscene, SIGNAL(changed()), this, SLOT(sceneChangeSignalled()));
connect(this, SIGNAL(moleculesVisibilityChanged(ObservedValue_Index_t,bool)),
worldscene, SLOT(moleculesVisibilityChanged(ObservedValue_Index_t,bool)));
// sign on to changes in the world
WorldTime::getInstance().signOn(this, WorldTime::TimeChanged);
AtomObserver::getInstance().signOn(this, AtomObservable::PositionChanged);
AtomObserver::getInstance().signOn(this, AtomObservable::VelocityChanged);
AtomObserver::getInstance().signOn(this, AtomObservable::ForceChanged);
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();
WorldTime::getInstance().signOff(this, WorldTime::TimeChanged);
AtomObserver::getInstance().signOff(this, AtomObservable::PositionChanged);
AtomObserver::getInstance().signOff(this, AtomObservable::VelocityChanged);
AtomObserver::getInstance().signOff(this, AtomObservable::ForceChanged);
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)
{
// world never dies
}
/** 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) == 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
needsRedraw = false;
emit changed();
emit TimeChanged();
break;
}
default:
ASSERT(0, "GLWorldView::recieveNotification() - we cannot get here for WorldTime.");
break;
}
} else if (static_cast(publisher) == ShapeRegistry::getPointer()) {
switch (notification->getChannelNo()) {
case ShapeRegistry::ShapeInserted:
{
needsRedraw = false;
emit ShapeAdded(ShapeRegistry::getInstance().lastChanged()->getName());
break;
}
case ShapeRegistry::ShapeRemoved:
{
needsRedraw = false;
emit ShapeRemoved(ShapeRegistry::getInstance().lastChanged()->getName());
break;
}
case ShapeRegistry::SelectionChanged:
{
needsRedraw = false;
worldscene->updateSelectedShapes();
break;
}
default:
ASSERT(0, "GLWorldView::recieveNotification() - we cannot get here for ShapeRegistry.");
break;
}
}
}
void GLWorldView::checkChanges()
{
needsRedraw = false;
updateGL();
}
void GLWorldView::changeDreiBein()
{
// invert to new status
const bool status = ((meshDreiBein->options() & QGLSceneNode::HideNode) == 0);
setdreiBeinStatus(!status);
// realize
needsRedraw = true;
emit changed();
}
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
needsRedraw = true;
emit changed();
}
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);
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)
{
// Find the distance between the eye and focus point.
QVector3D d = camera()->eye() - camera()->center();
// LOG(1, "Distance vector eye and center is "
// << d.x() << "," << d.y() << "," << d.z());
// scale the move unit by the eye <-> domain center distance
const double key_move_unit = 0.04*(d.length()/50.);
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();
} else if ((e->key() == Qt::Key_Minus) || (e->key() == Qt::Key_Plus)) {
// Scale the distance.
if (e->key() == Qt::Key_Minus)
d *= 1.2;
else if (e->key() == Qt::Key_Plus)
d /= 1.2;
// Set new eye position.
camera()->setEye(camera()->center() + d);
} else if ((e->key() == Qt::Key_Left) || (e->key() == Qt::Key_Right)) {
// Translate the camera.
const double d = (e->key() == Qt::Key_Left) ? -key_move_unit : key_move_unit;
camera()->translateCenter( d, 0., 0);
camera()->translateEye( d, 0., 0);
} else if ((e->key() == Qt::Key_Up) || (e->key() == Qt::Key_Down)) {
// Translate the camera.
const double d = (e->key() == Qt::Key_Up) ? -key_move_unit : key_move_unit;
camera()->translateCenter( 0., d, 0);
camera()->translateEye( 0., d, 0);
} else if ((e->key() == Qt::Key_PageUp) || (e->key() == Qt::Key_PageDown)) {
// Translate the camera.
const double d = (e->key() == Qt::Key_PageUp) ? -key_move_unit : key_move_unit;
camera()->translateCenter( 0., 0., d);
camera()->translateEye( 0., 0., d);
}
QGLView::keyPressEvent(e);
}
void GLWorldView::changeSignalled()
{
changesPresent = true;
updateGL();
}
/**
* 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);
emit changed();
}
void GLWorldView::setCameraStereoModeHardware()
{
setStereoType(QGLView::Hardware);
camera()->setEyeSeparation(defaultEyeSeparation);
emit changed();
}
void GLWorldView::setCameraStereoModeLeftRight()
{
setStereoType(QGLView::LeftRight);
camera()->setEyeSeparation(defaultEyeSeparation);
emit changed();
}
void GLWorldView::setCameraStereoModeRightLeft()
{
setStereoType(QGLView::RightLeft);
camera()->setEyeSeparation(defaultEyeSeparation);
emit changed();
}
void GLWorldView::setCameraStereoModeTopBottom()
{
setStereoType(QGLView::TopBottom);
camera()->setEyeSeparation(defaultEyeSeparation);
emit changed();
}
void GLWorldView::setCameraStereoModeBottomTop()
{
setStereoType(QGLView::BottomTop);
camera()->setEyeSeparation(defaultEyeSeparation);
emit changed();
}
void GLWorldView::setCameraStereoModeAnaglyph()
{
setStereoType(QGLView::RedCyanAnaglyph);
camera()->setEyeSeparation(defaultEyeSeparation);
emit changed();
}
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 atomId_t _id)
{
needsRedraw = true;
emit changed();
emit hoverChanged(_id);
}
void GLWorldView::sceneHoverSignalled(const moleculeId_t _id, int _i)
{
needsRedraw = true;
emit changed();
emit hoverChanged(_id, _i);
}