mirror of https://github.com/CGAL/cgal
423 lines
13 KiB
C++
423 lines
13 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 Coords}
|
|
, pos_emptySphere{new Coords}
|
|
, points_emptySphere{new Coords}
|
|
, pos_points{new Coords}
|
|
, pos_newPoint{new Coords}
|
|
, pos_selectedVertex{new Coords}
|
|
, pos_movingPoint{new Coords}
|
|
, pos_queryPoint{new Coords}
|
|
, pos_trackBall{ new Coords}
|
|
, pos_voronoi{new Coords}
|
|
, pos_delaunay{new Coords}
|
|
, pos_facets{new Coords}
|
|
, pos_newFacet{new Coords}
|
|
, pos_nearest_neighbor{new Coords}
|
|
, points_locationSphere{new Coords}
|
|
, points_cylinder{new Coords}
|
|
, normals_cylinder{new Coords}
|
|
, points_sphere{new Coords}
|
|
, points_trackBall{new Coords}
|
|
, normals_sphere{new Coords}
|
|
, normals_emptySphere{new Coords}
|
|
, normals_trackBall{new Coords}
|
|
, transfo1_voronoi{new Coords}
|
|
, transfo2_voronoi{new Coords}
|
|
, transfo3_voronoi{new Coords}
|
|
, transfo4_voronoi{new Coords}
|
|
, transfo1_delaunay{new Coords}
|
|
, transfo2_delaunay{new Coords}
|
|
, transfo3_delaunay{new Coords}
|
|
, transfo4_delaunay{new Coords}
|
|
, incremental_points{new Coords}
|
|
, incremental_next_point{new Coords}
|
|
, incremental_facet{new Coords}
|
|
, incremental_conflict{new Coords}
|
|
{}
|
|
|
|
~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:
|
|
using Coords = std::vector<float>;
|
|
using Coords_ptr = std::unique_ptr<std::vector<float>>;
|
|
|
|
// draw a 3d effect vertex
|
|
void drawVertex(const Point_3& p, Coords_ptr& vertices);
|
|
// draw a 3d effect edge
|
|
void drawEdge(const Point_3& from, const Point_3 &to, Coords_ptr& vertices);
|
|
// draw a facet
|
|
void drawFacet(const Triangle_3& t, Coords_ptr& 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;
|
|
|
|
Coords_ptr pos_emptyFacet;
|
|
Coords_ptr pos_emptySphere;
|
|
Coords_ptr points_emptySphere;
|
|
Coords_ptr pos_points;
|
|
Coords_ptr pos_newPoint;
|
|
Coords_ptr pos_selectedVertex;
|
|
Coords_ptr pos_movingPoint;
|
|
Coords_ptr pos_queryPoint;
|
|
Coords_ptr pos_trackBall;
|
|
Coords_ptr pos_voronoi;
|
|
Coords_ptr pos_delaunay;
|
|
Coords_ptr pos_facets;
|
|
Coords_ptr pos_newFacet;
|
|
Coords_ptr pos_nearest_neighbor;
|
|
Coords_ptr points_locationSphere;
|
|
Coords_ptr points_cylinder;
|
|
Coords_ptr normals_cylinder;
|
|
Coords_ptr points_sphere;
|
|
Coords_ptr points_trackBall;
|
|
Coords_ptr normals_sphere;
|
|
Coords_ptr normals_emptySphere;
|
|
Coords_ptr normals_trackBall;
|
|
Coords_ptr transfo1_voronoi;
|
|
Coords_ptr transfo2_voronoi;
|
|
Coords_ptr transfo3_voronoi;
|
|
Coords_ptr transfo4_voronoi;
|
|
Coords_ptr transfo1_delaunay;
|
|
Coords_ptr transfo2_delaunay;
|
|
Coords_ptr transfo3_delaunay;
|
|
Coords_ptr transfo4_delaunay;
|
|
Coords_ptr incremental_points;
|
|
Coords_ptr incremental_next_point;
|
|
Coords_ptr incremental_facet;
|
|
Coords_ptr incremental_conflict;
|
|
//pickin
|
|
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, Coords_ptr& vertices, Coords_ptr& normals);
|
|
void draw_sphere(float R, int prec, Coords_ptr& vertices, Coords_ptr& normals);
|
|
};
|
|
|
|
#endif
|