cgal/Triangulation_3/demo/Triangulation_3/Viewer.h

422 lines
14 KiB
C++

#ifndef VIEWER_H
#define VIEWER_H
#include "Scene.h"
#include <QMap>
#include <CGAL/Qt/qglviewer.h>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QSettings>
#include "PreferenceDlg.h"
#include <QOpenGLFunctions_2_1>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <CGAL/Qt/CreateOpenGLContext.h>
#include <iostream>
using namespace CGAL::qglviewer;
class MainWindow;
class Viewer : public CGAL::QGLViewer{
Q_OBJECT
public:
Viewer(QWidget* parent)
: CGAL::QGLViewer(parent)
, m_showAxis(false)
, m_showVertex(true)
, m_showDEdge(true)
, m_showVEdge(false)
, m_showFacet(false)
, m_isFlat(false)
, m_fRadius(1.)
, m_curMode(NONE)
, m_isPress(false)
, m_isMoving(false)
, m_hasNewPt(false)
, m_selMode(NORMAL)
, m_nearestNb(nullptr)
, m_hasEmptyS(false)
, m_showTrackball(true)
, m_pDlgPrefer(nullptr)
{
pos_emptyFacet = new std::vector<float>();
pos_emptySphere= new std::vector<float>();
points_emptySphere = new std::vector<float>();
pos_points = new std::vector<float>();
pos_newPoint = new std::vector<float>();
pos_selectedVertex = new std::vector<float>();
pos_movingPoint = new std::vector<float>();
pos_queryPoint = new std::vector<float>();
pos_trackBall = new std::vector<float>();
pos_voronoi = new std::vector<float>();
pos_delaunay = new std::vector<float>();
pos_facets = new std::vector<float>();
pos_newFacet = new std::vector<float>();
pos_nearest_neighbor = new std::vector<float>();
points_locationSphere = new std::vector<float>();
points_cylinder = new std::vector<float>();
normals_cylinder = new std::vector<float>();
points_sphere = new std::vector<float>();
points_trackBall = new std::vector<float>();
normals_sphere = new std::vector<float>();
normals_emptySphere = new std::vector<float>();
normals_trackBall= new std::vector<float>();
transfo1_voronoi = new std::vector<float>();
transfo2_voronoi = new std::vector<float>();
transfo3_voronoi = new std::vector<float>();
transfo4_voronoi = new std::vector<float>();
transfo1_delaunay = new std::vector<float>();
transfo2_delaunay = new std::vector<float>();
transfo3_delaunay = new std::vector<float>();
transfo4_delaunay = new std::vector<float>();
incremental_points = new std::vector<float>();
incremental_next_point = new std::vector<float>();
incremental_facet = new std::vector<float>();
incremental_conflict = new std::vector<float>();
}
~Viewer()
{
for(int i=0; i< vboSize; i++)
buffers[i].destroy();
for(int i=0; i< vaoSize; i++)
vao[i].destroy();
}
enum Mode { NONE, INSERT_V, INSERT_PT, MOVE, SELECT, FINDNB, EMPTYSPH };
public:
inline void setScene(Scene* pScene) { m_pScene = pScene; }
// set current mode
inline void setMode(Mode m) {
m_curMode = m;
m_isMoving = false;
m_hasEmptyS = false;
m_nearestNb = nullptr;
update();
}
// set selectBuffer size (if necessary)
inline void setSelBuffSize() {
// Default selectBuffer size is 4000
// (i.e. 1000 objects in selection region, since each object pushes 4 values).
if( m_pScene->m_vhArray.size() > 900 )
// The previous selectBuffer is deleted and a new one is created.
setSelectBufferSize( 4*(m_pScene->m_vhArray.size() + 100) );
}
void readSettings() {
// read from an .ini file
QSettings settings("settings.ini", QSettings::IniFormat);
// QVariant value ( const QString & key, const QVariant & defaultValue = QVariant() )
// Because QVariant is part of the QtCore library,
// it cannot provide conversion functions to data types such as QColor and QImage,
// which are part of QtGui.
// In other words, there is no toColor(), toImage(), or toPixmap() functions in QVariant.
// Instead, use the QVariant::value() or the qVariantValue() template function
m_colorVertex = settings.value( "Show/vertexcolor", QColor(255, 150, 0) ).value<QColor>();
m_fSizeVertex = settings.value( "Show/vertexsize", 0.04f ).toFloat();
m_colorDEdge = settings.value( "Show/dedgecolor", QColor(0, 255, 0) ).value<QColor>();
m_fSizeDEdge = settings.value( "Show/dedgesize", 0.01f ).toFloat();
m_colorVEdge = settings.value( "Show/vedgecolor", QColor(0, 0, 255) ).value<QColor>();
m_fSizeVEdge = settings.value( "Show/vedgesize", 0.01f ).toFloat();
m_colorFacet = settings.value( "Show/facetcolor",
QColor(255, 255, 0, 96) ).value<QColor>();
m_colorTrackball = settings.value( "Show/ballcolor",
QColor(150, 150, 150, 128) ).value<QColor>();
m_iStep = settings.value( "Show/ballstep", 4000 ).toInt();
m_colorEmptySphere = settings.value( "Show/spherecolor",
QColor(180, 50, 180, 64) ).value<QColor>();
}
void writeSettings() {
// write to an .ini file
QSettings settings("settings.ini", QSettings::IniFormat);
// The inverse conversion (e.g., from QColor to QVariant) is automatic
// for all data types supported by QVariant, including GUI-related types
settings.setValue("Show/vertexcolor", m_colorVertex);
settings.setValue("Show/vertexsize", m_fSizeVertex);
settings.setValue("Show/dedgecolor", m_colorDEdge);
settings.setValue("Show/dedgesize", m_fSizeDEdge);
settings.setValue("Show/vedgecolor", m_colorVEdge);
settings.setValue("Show/vedgesize", m_fSizeVEdge);
settings.setValue("Show/facetcolor", m_colorFacet);
settings.setValue("Show/ballcolor", m_colorTrackball);
settings.setValue("Show/ballstep", m_iStep);
settings.setValue("Show/spherecolor", m_colorEmptySphere);
}
public Q_SLOTS:
// clear scene
void changed()
{
compute_elements();
are_buffers_initialized = false;
}
void clear() {
m_pScene->eraseOldData();
m_hasNewPt = false;
m_boundaryFacets.clear();
m_conflictCells.clear();
m_vidSeled.clear();
m_isMoving = false;
m_nearestNb = nullptr;
m_hasEmptyS = false;
if( !m_incrementalPts.isEmpty() ) {
Q_EMIT( stopIncAnimation() );
m_incrementalPts.clear();
}
}
// play/pause incremental construction
void toggleIncremental(bool on);
// clean up old data and information
void initClean() {
m_pScene->eraseOldData();
m_hasNewPt = false;
m_boundaryFacets.clear();
m_conflictCells.clear();
m_vidSeled.clear();
m_isMoving = false;
m_nearestNb = nullptr;
m_hasEmptyS = false;
}
// stop incremental construction
void stopIncremental();
// incremental insert a vertex (invoked by Timer)
void incremental_insert();
// show options
inline void toggleShowAxis(bool flag) {
m_showAxis = flag;
update();
}
inline void toggleShowVertex(bool flag) { m_showVertex = flag;
update();
}
inline void toggleShowDEdge(bool flag) { m_showDEdge = flag;
update();
}
inline void toggleShowVEdge(bool flag) { m_showVEdge = flag;
update();
}
inline void toggleShowFacet(bool flag) { m_showFacet = flag;
update();
}
inline void toggleFlat(bool flag) { m_isFlat = flag;
update();
}
// set preferences
void setPreferences() {
if (!m_pDlgPrefer) {
m_pDlgPrefer = new PreferenceDlg(this);
m_pDlgPrefer->init( m_colorVertex, m_fSizeVertex, m_colorDEdge, m_fSizeDEdge, m_colorVEdge, m_fSizeVEdge,
m_colorFacet, m_colorTrackball, m_colorEmptySphere, m_iStep/40 ); // 5*8, 5 degrees of wheel
connect(m_pDlgPrefer, SIGNAL(applyChanges()), this, SLOT(acceptChanges()) );
}
m_pDlgPrefer->show();
m_pDlgPrefer->raise();
m_pDlgPrefer->activateWindow();
}
void acceptChanges() {
m_colorVertex = m_pDlgPrefer->m_colorVertex;
m_fSizeVertex = m_pDlgPrefer->m_fSizeVertex;
m_colorDEdge = m_pDlgPrefer->m_colorDEdge;
m_fSizeDEdge = m_pDlgPrefer->m_fSizeDEdge;
m_colorVEdge = m_pDlgPrefer->m_colorVEdge;
m_fSizeVEdge = m_pDlgPrefer->m_fSizeVEdge;
m_colorFacet = m_pDlgPrefer->m_colorFacet;
m_colorTrackball = m_pDlgPrefer->m_colorTrackball;
m_iStep = m_pDlgPrefer->m_iStep*40;
m_colorEmptySphere = m_pDlgPrefer->m_colorEmptySphere;
// redraw
update();
}
Q_SIGNALS:
void stopIncAnimation();
// overloading CGAL::QGLViewer virtual functions
protected:
// initialize Viewer OpenGL context
// Note: the default implement is empty and this is overloading.
void init();
// draw points, segments, and polygons
void draw();
// customize selection process
void beginSelection(const QPoint &point);
void drawWithNames();
void endSelection(const QPoint&);
// customize mouse events
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
// customize key events
void keyPressEvent(QKeyEvent *event);
// customize help message
QString helpString() const;
private:
// draw a 3d effect vertex
void drawVertex(const Point_3& p, std::vector<float> *vertices);
// draw a 3d effect edge
void drawEdge(const Point_3& from, const Point_3 &to, std::vector<float> *vertices);
// draw a facet
void drawFacet(const Triangle_3& t, std::vector<float> *vertices);
// test whether the give 3D point is on the sphere
inline bool isOnSphere( const Point_3 & pt ) {
return ( (pt.x()*pt.x() + pt.y()*pt.y() + pt.z()*pt.z()) == (m_fRadius*m_fRadius) );
}
// compute the intersection point with the sphere
bool computeIntersect( const QPoint & pos, Vec & pt );
// compute the conflict region
void computeConflict( Point_3 pt );
private:
Scene* m_pScene;
// play timer
QTimer* m_pTimer;
Point_3 m_curIncPt;
QList<Point_3> m_incrementalPts;
enum Step { INIT, NEWPT, CELL, CONFLICT };
Step m_curStep;
Cell_handle m_cellContain;
QList<Facet> m_boundaryFacets;
QList<Cell_handle> m_conflictCells;
// show options
bool m_showAxis;
bool m_showVertex;
bool m_showDEdge;
bool m_showVEdge;
bool m_showFacet;
bool m_isFlat;
// trackball
float m_fRadius;
// mode
Mode m_curMode;
bool m_isPress;
bool m_isMoving;
// insert point
bool m_hasNewPt;
Point_3 m_newPt;
// select vertex
enum selectionMode { NORMAL, ADD };
selectionMode m_selMode;
QRect m_rectSel;
QList<int> m_vidSeled;
// move vertex/point
int m_vidMoving;
// nearest neighbor
Point_3 m_queryPt;
Vertex_handle m_nearestNb;
// empty sphere
bool m_hasEmptyS;
bool m_showTrackball;
Point_3 m_centerPt;
float m_fREmptyS;
// change colors
PreferenceDlg* m_pDlgPrefer;
float m_fSizeVertex;
float m_fSizeDEdge;
float m_fSizeVEdge;
QColor m_colorVertex;
QColor m_colorDEdge;
QColor m_colorVEdge;
QColor m_colorFacet;
QColor m_colorTrackball;
QColor m_colorEmptySphere;
// trackball resizing fineness
int m_iStep;
QColor color;
static const int vaoSize = 29;
static const int vboSize = 34;
// define material
QVector4D ambient;
QVector4D diffuse;
QVector4D specular;
GLfloat shininess ;
int poly_vertexLocation[3];
int normalsLocation[3];
int mvpLocation[3];
int mvLocation[2];
int centerLocation[5];
int colorLocation[3];
int lightLocation[5*2];
bool are_buffers_initialized;
bool extension_is_found;
std::vector<float> *pos_emptyFacet;
std::vector<float> *pos_emptySphere;
std::vector<float> *points_emptySphere;
std::vector<float> *pos_points;
std::vector<float> *pos_newPoint;
std::vector<float> *pos_selectedVertex;
std::vector<float> *pos_movingPoint;
std::vector<float> *pos_queryPoint;
std::vector<float> *pos_trackBall;
std::vector<float> *points_trackBall;
std::vector<float> *pos_voronoi;
std::vector<float> *pos_delaunay;
std::vector<float> *pos_facets;
std::vector<float> *pos_newFacet;
std::vector<float> *pos_nearest_neighbor;
std::vector<float> *points_locationSphere;
std::vector<float> *points_cylinder;
std::vector<float> *normals_cylinder;
std::vector<float> *points_sphere;
std::vector<float> *normals_sphere;
std::vector<float> *normals_emptySphere;
std::vector<float> *normals_trackBall;
std::vector<float> *transfo1_voronoi;
std::vector<float> *transfo2_voronoi;
std::vector<float> *transfo3_voronoi;
std::vector<float> *transfo4_voronoi;
std::vector<float> *transfo1_delaunay;
std::vector<float> *transfo2_delaunay;
std::vector<float> *transfo3_delaunay;
std::vector<float> *transfo4_delaunay;
std::vector<float> *incremental_points;
std::vector<float> *incremental_next_point;
std::vector<float> *incremental_facet;
std::vector<float> *incremental_conflict;
//picking
QMap<float, int> picked_IDs;
QPoint picking_pos;
QOpenGLBuffer buffers[vboSize];
QOpenGLVertexArrayObject vao[vaoSize];
QOpenGLShaderProgram rendering_program;
QOpenGLShaderProgram rendering_program_spheres;
QOpenGLShaderProgram rendering_program_cylinders;
typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor);
PFNGLDRAWARRAYSINSTANCEDARBPROC glDrawArraysInstanced;
PFNGLVERTEXATTRIBDIVISORARBPROC glVertexAttribDivisor;
void initialize_buffers();
void compute_elements();
void attrib_buffers(CGAL::QGLViewer*);
void compile_shaders();
void draw_cylinder(float R, int prec, std::vector<float> *vertices, std::vector<float> *normals);
void draw_sphere(float R, int prec, std::vector<float> *vertices, std::vector<float> *normals);
};
#endif