cgal/Polyhedron/demo/Polyhedron/Viewer.cpp

262 lines
6.1 KiB
C++

#include "Viewer.h"
#include "Scene_draw_interface.h"
#include <QMouseEvent>
#include <QKeyEvent>
class Viewer_impl {
public:
Scene_draw_interface* scene;
bool antialiasing;
bool twosides;
bool macro_mode;
void draw_aux(bool with_names);
};
Viewer::Viewer(QWidget* parent, bool antialiasing)
: QGLViewer(parent)
{
d = new Viewer_impl;
d->scene = 0;
d->antialiasing = antialiasing;
d->twosides = false;
d->macro_mode = false;
setShortcut(EXIT_VIEWER, 0);
setMouseBinding(Qt::SHIFT + Qt::LeftButton, SELECT);
setMouseBindingDescription(Qt::SHIFT + Qt::RightButton,
tr("Selects and display context "
"menu of the selected item"));
setKeyDescription(Qt::Key_T,
tr("Turn the camera by 180 degrees"));
setKeyDescription(Qt::Key_M,
tr("Toggle macro mode: useful to view details very near from the camera, "
"but decrease the z-buffer precision"));
}
Viewer::~Viewer()
{
delete d;
}
void Viewer::setScene(Scene_draw_interface* scene)
{
d->scene = scene;
}
bool Viewer::antiAliasing() const
{
return d->antialiasing;
}
void Viewer::setAntiAliasing(bool b)
{
d->antialiasing = b;
updateGL();
}
void Viewer::setTwoSides(bool b)
{
d->twosides = b;
updateGL();
}
void Viewer::draw()
{
// ::glFogf(GL_FOG_END, 2*sceneRadius());
// ::glEnable(GL_FOG);
QGLViewer::draw();
d->draw_aux(false);
// drawLight(GL_LIGHT0);
}
void Viewer::initializeGL()
{
QGLViewer::initializeGL();
setBackgroundColor(::Qt::white);
d->scene->initializeGL();
const GLfloat ambient_light[4] = { 0.6f, 0.6f, 0.6f, 1.0f };
const GLfloat diffuse_light[4] = { 0.6f, 0.6f, 0.6f, 1.0f };
::glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_light);
::glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_light);
// ::glFogf(GL_FOG_DENSITY, 0.05f);
// ::glHint(GL_FOG_HINT, GL_NICEST);
// ::glFogi(GL_FOG_MODE, GL_LINEAR);
// static const GLfloat fogColor[] = {0.5f, 0.5f, 0.5f, 1};
// ::glFogfv(GL_FOG_COLOR, fogColor);
}
#include <QMouseEvent>
void Viewer::mousePressEvent(QMouseEvent* event)
{
if(event->button() == Qt::RightButton &&
event->modifiers().testFlag(Qt::ShiftModifier))
{
select(event->pos());
requestContextMenu(event->globalPos());
event->accept();
}
else {
QGLViewer::mousePressEvent(event);
}
}
void Viewer::keyPressEvent(QKeyEvent* e)
{
if(!e->modifiers()) {
if(e->key() == Qt::Key_T) {
turnCameraBy180Degres();
return;
}
else if(e->key() == Qt::Key_M) {
d->macro_mode = ! d->macro_mode;
if(d->macro_mode) {
camera()->setZNearCoefficient(0.0005f);
} else {
camera()->setZNearCoefficient(0.005f);
}
this->displayMessage(tr("Macro mode: %1").
arg(d->macro_mode ? tr("on") : tr("off")));
return;
}
}
QGLViewer::keyPressEvent(e);
}
void Viewer::turnCameraBy180Degres() {
qglviewer::Camera* camera = this->camera();
using qglviewer::ManipulatedCameraFrame;
ManipulatedCameraFrame frame_from(*camera->frame());
camera->setViewDirection(-camera->viewDirection());
ManipulatedCameraFrame frame_to(*camera->frame());
camera->setOrientation(frame_from.orientation());
camera->interpolateTo(frame_to, 0.5f);
}
void Viewer_impl::draw_aux(bool with_names)
{
if(scene == 0)
return;
::glLineWidth(1.0f);
::glPointSize(2.f);
::glEnable(GL_POLYGON_OFFSET_FILL);
::glPolygonOffset(1.0f,1.0f);
::glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
::glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
if(twosides)
::glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
else
::glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
if(antialiasing)
{
::glEnable(GL_BLEND);
::glEnable(GL_LINE_SMOOTH);
::glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
::glDisable(GL_BLEND);
::glDisable(GL_LINE_SMOOTH);
::glDisable(GL_POLYGON_SMOOTH_HINT);
::glBlendFunc(GL_ONE, GL_ZERO);
::glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
}
if(with_names)
scene->drawWithNames();
else
scene->draw();
}
void Viewer::drawWithNames()
{
QGLViewer::draw();
d->draw_aux(true);
}
void Viewer::postSelection(const QPoint& pixel)
{
bool found = false;
qglviewer::Vec point = camera()->pointUnderPixel(pixel, found);
if(found) {
emit selectedPoint(point.x,
point.y,
point.z);
emit selected(this->selectedName());
const qglviewer::Vec orig = camera()->position();
const qglviewer::Vec dir = point - orig;
emit selectionRay(orig.x, orig.y, orig.z,
dir.x, dir.y, dir.z);
}
}
bool Viewer::readFrame(QString s, qglviewer::Frame& frame)
{
QStringList list = s.split(" ", QString::SkipEmptyParts);
if(list.size() != 7)
return false;
float vec[3];
for(int i = 0; i < 3; ++i)
{
bool ok;
vec[i] = list[i].toFloat(&ok);
if(!ok) return false;
}
double orient[4];
for(int i = 0; i < 4; ++i)
{
bool ok;
orient[i] = list[i + 3].toDouble(&ok);
if(!ok) return false;
}
frame.setPosition(qglviewer::Vec(vec[0],
vec[1],
vec[2]));
frame.setOrientation(orient[0],
orient[1],
orient[2],
orient[3]);
return true;
}
QString Viewer::dumpFrame(const qglviewer::Frame& frame) {
const qglviewer::Vec pos = frame.position();
const qglviewer::Quaternion q = frame.orientation();
return QString("%1 %2 %3 %4 %5 %6 %7")
.arg(pos[0])
.arg(pos[1])
.arg(pos[2])
.arg(q[0])
.arg(q[1])
.arg(q[2])
.arg(q[3]);
}
bool Viewer::moveCameraToCoordinates(QString s, float animation_duration) {
qglviewer::Frame new_frame;
if(readFrame(s, new_frame)) {
camera()->interpolateTo(new_frame, animation_duration);
return true;
}
else
return false;
}
QString Viewer::dumpCameraCoordinates()
{
if(camera()->frame()) {
return dumpFrame(*camera()->frame());
} else {
return QString();
}
}