mirror of https://github.com/CGAL/cgal
377 lines
9.4 KiB
C++
377 lines
9.4 KiB
C++
#include "Viewer.h"
|
|
#include <compute_normal.h>
|
|
#include <vector>
|
|
#include <CGAL/bounding_box.h>
|
|
#include <QGLViewer/vec.h>
|
|
|
|
template<class Map>
|
|
CGAL::Bbox_3 bbox(Map& amap)
|
|
{
|
|
CGAL::Bbox_3 bb;
|
|
typename Map::Vertex_iterator it = amap.vertices_begin();
|
|
if ( it!=amap.vertices_end() )
|
|
{
|
|
bb = it->point().bbox();
|
|
for( ++it; it != amap.vertices_end(); ++it)
|
|
{
|
|
bb = bb + it->point().bbox();
|
|
}
|
|
}
|
|
|
|
return bb;
|
|
}
|
|
|
|
void
|
|
Viewer::sceneChanged()
|
|
{
|
|
|
|
CGAL::Bbox_3 bb = bbox(scene->map);
|
|
|
|
this->camera()->setSceneBoundingBox(qglviewer::Vec(bb.xmin(),
|
|
bb.ymin(),
|
|
bb.zmin()),
|
|
qglviewer::Vec(bb.xmax(),
|
|
bb.ymax(),
|
|
bb.zmax()));
|
|
|
|
this->showEntireScene();
|
|
}
|
|
|
|
// Draw the face given by ADart
|
|
void Viewer::drawFace(Dart_handle ADart, int AMark)
|
|
{
|
|
Map &m = scene->map;
|
|
::glBegin(GL_POLYGON);
|
|
::glColor3f(.7,.7,.7);
|
|
|
|
// If Flat shading: 1 normal per polygon
|
|
if (flatShading)
|
|
{
|
|
Map::Vector n = compute_facet_normal(m,ADart);
|
|
::glNormal3d(n.x(),n.y(),n.z());
|
|
}
|
|
|
|
for ( Map::Dart_iterator_of_beta1 it(m,ADart); it.cont(); ++it)
|
|
{
|
|
// If Gouraud shading: 1 normal per vertex
|
|
if (!flatShading)
|
|
{
|
|
Map::Vector n = compute_vertex_normal<Map>(m,*it);
|
|
::glNormal3d(n.x(),n.y(),n.z());
|
|
}
|
|
|
|
Map::Point p = it->vertex()->point();
|
|
::glVertex3d( p.x(),p.y(),p.z());
|
|
|
|
m.set_mark(*it,AMark);
|
|
if ( !it->is_free(3) ) m.set_mark(it->beta(3),AMark);
|
|
}
|
|
::glEnd();
|
|
}
|
|
|
|
/// Draw all the edge of the face given by ADart
|
|
void Viewer::drawEdges(Dart_handle ADart)
|
|
{
|
|
Map &m = scene->map;
|
|
glBegin(GL_LINES);
|
|
glColor3f(.2,.2,.6);
|
|
for ( Map::Dart_iterator_of_beta1 it(m,ADart); it.cont(); ++it)
|
|
{
|
|
Map::Point p = it->vertex()->point();
|
|
Dart_handle d2 = it->opposite_dart();
|
|
if ( d2!=NULL )
|
|
{
|
|
Map::Point p2 = d2->vertex()->point();
|
|
glVertex3f( p.x(),p.y(),p.z());
|
|
glVertex3f( p2.x(),p2.y(),p2.z());
|
|
}
|
|
}
|
|
glEnd();
|
|
}
|
|
|
|
|
|
void Viewer::draw()
|
|
{
|
|
Map &m = scene->map;
|
|
|
|
unsigned int facetreated = m.get_new_mark();
|
|
unsigned int vertextreated = -1;
|
|
|
|
if ( vertices) vertextreated=m.get_new_mark();
|
|
|
|
for(Map::Dart_iterator_of_all it(m); it.cont(); ++it)
|
|
{
|
|
if ( !m.is_marked(*it,facetreated) )
|
|
{
|
|
drawFace(*it,facetreated);
|
|
if ( edges) drawEdges(*it);
|
|
}
|
|
|
|
if (vertices)
|
|
{
|
|
if ( !m.is_marked(*it, vertextreated) )
|
|
{
|
|
Map::Point p = it->vertex()->point();
|
|
|
|
glBegin(GL_POINTS);
|
|
glColor3f(.6,.2,.8);
|
|
glVertex3f( p.x(),p.y(),p.z());
|
|
glEnd();
|
|
|
|
mark_orbit(m,*it,Map::VERTEX_ORBIT,vertextreated);
|
|
}
|
|
}
|
|
}
|
|
|
|
assert(m.is_whole_map_marked(facetreated));
|
|
|
|
if ( vertices)
|
|
{
|
|
assert(m.is_whole_map_marked(vertextreated));
|
|
m.free_mark(vertextreated);
|
|
}
|
|
|
|
m.free_mark(facetreated);
|
|
}
|
|
|
|
/*
|
|
void
|
|
Viewer::draw()
|
|
{
|
|
|
|
// define material
|
|
float ambient[] = { 0.25f,
|
|
0.20725f,
|
|
0.20725f,
|
|
0.922f };
|
|
float diffuse[] = { 1.0f,
|
|
0.829f,
|
|
0.829f,
|
|
0.922f };
|
|
|
|
float specular[] = { 0.296648f,
|
|
0.296648f,
|
|
0.296648f,
|
|
0.522f };
|
|
|
|
float emission[] = { 0.3f,
|
|
0.3f,
|
|
0.3f,
|
|
1.0f };
|
|
float shininess[] = { 11.264f };
|
|
|
|
// apply material
|
|
::glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
|
|
::glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
|
|
::glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, specular);
|
|
::glMaterialfv( GL_FRONT_AND_BACK, GL_SHININESS, shininess);
|
|
::glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, emission);
|
|
|
|
// anti-aliasing (if the OpenGL driver permits that)
|
|
::glEnable(GL_LINE_SMOOTH);
|
|
|
|
::glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
|
|
// draw surface mesh
|
|
bool m_view_surface = true;
|
|
bool draw_triangles_edges = true;
|
|
|
|
if(m_view_surface)
|
|
{
|
|
::glEnable(GL_LIGHTING);
|
|
::glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
|
::glColor3f(0.2f, 0.2f, 1.f);
|
|
::glEnable(GL_POLYGON_OFFSET_FILL);
|
|
::glPolygonOffset(3.0f,-3.0f);
|
|
gl_draw_surface();
|
|
|
|
if(draw_triangles_edges)
|
|
{
|
|
::glDisable(GL_LIGHTING);
|
|
::glLineWidth(1.);
|
|
::glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
|
::glColor3ub(0,0,0);
|
|
::glDisable(GL_POLYGON_OFFSET_FILL);
|
|
gl_draw_surface();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void
|
|
Viewer::gl_draw_surface()
|
|
{
|
|
::glColor3f(1.0f, 0.0f, 0.0f);
|
|
::glDisable(GL_LIGHTING);
|
|
::glEnable(GL_POINT_SMOOTH);
|
|
::glPointSize(5);
|
|
::glBegin(GL_POINTS);
|
|
|
|
for(std::list<Point_3>::iterator it = scene->points.begin();
|
|
it != scene->points.end();
|
|
++it){
|
|
::glVertex3d(it->x(), it->y(), it->z());
|
|
}
|
|
|
|
::glEnd();
|
|
::glDisable(GL_POINT_SMOOTH);
|
|
|
|
::glEnable(GL_LIGHTING);
|
|
::glBegin(GL_TRIANGLES);
|
|
|
|
::glColor3f(0.2f, 1.0f, 0.2f);
|
|
|
|
std::list<Facet> facets;
|
|
scene->alpha_shape.get_alpha_shape_facets(std::back_inserter(facets), Alpha_shape_3::REGULAR);
|
|
|
|
for(std::list<Facet>::iterator fit = facets.begin();
|
|
fit != facets.end();
|
|
++fit) {
|
|
const Cell_handle& ch = fit->first;
|
|
const int index = fit->second;
|
|
|
|
//const Vector_3& n = ch->normal(index); // must be unit vector
|
|
|
|
const Point_3& a = ch->vertex((index+1)&3)->point();
|
|
const Point_3& b = ch->vertex((index+2)&3)->point();
|
|
const Point_3& c = ch->vertex((index+3)&3)->point();
|
|
|
|
Vector_3 v = CGAL::unit_normal(a,b,c);
|
|
|
|
|
|
::glNormal3d(v.x(),v.y(),v.z());
|
|
::glVertex3d(a.x(),a.y(),a.z());
|
|
::glVertex3d(b.x(),b.y(),b.z());
|
|
::glVertex3d(c.x(),c.y(),c.z());
|
|
}
|
|
|
|
|
|
::glEnd();
|
|
|
|
}
|
|
*/
|
|
|
|
|
|
void Viewer::init()
|
|
{
|
|
// Restore previous viewer state.
|
|
restoreStateFromFile();
|
|
|
|
// Define 'Control+Q' as the new exit shortcut (default was 'Escape')
|
|
setShortcut(EXIT_VIEWER, Qt::CTRL+Qt::Key_Q);
|
|
|
|
// Add custom key description (see keyPressEvent).
|
|
setKeyDescription(Qt::Key_W, "Toggles wire frame display");
|
|
setKeyDescription(Qt::Key_F, "Toggles flat shading display");
|
|
setKeyDescription(Qt::Key_E, "Toggles edges display");
|
|
setKeyDescription(Qt::Key_V, "Toggles vertices display");
|
|
|
|
// Light default parameters
|
|
::glLineWidth(1.4f);
|
|
::glPointSize(4.f);
|
|
::glEnable(GL_POLYGON_OFFSET_FILL);
|
|
::glPolygonOffset(1.0f,1.0f);
|
|
::glClearColor(1.0f,1.0f,1.0f,0.0f);
|
|
::glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
|
|
|
::glEnable(GL_LIGHTING);
|
|
|
|
::glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
|
|
// ::glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
|
|
|
|
if (flatShading)
|
|
{
|
|
::glShadeModel(GL_FLAT);
|
|
::glDisable(GL_BLEND);
|
|
::glDisable(GL_LINE_SMOOTH);
|
|
::glDisable(GL_POLYGON_SMOOTH_HINT);
|
|
::glBlendFunc(GL_ONE, GL_ZERO);
|
|
::glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
|
|
}
|
|
else
|
|
{
|
|
::glShadeModel(GL_SMOOTH);
|
|
::glEnable(GL_BLEND);
|
|
::glEnable(GL_LINE_SMOOTH);
|
|
::glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
|
|
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
}
|
|
|
|
void Viewer::keyPressEvent(QKeyEvent *e)
|
|
{
|
|
const Qt::KeyboardModifiers modifiers = e->modifiers();
|
|
|
|
bool handled = false;
|
|
if ((e->key()==Qt::Key_W) && (modifiers==Qt::NoButton))
|
|
{
|
|
wireframe = !wireframe;
|
|
if (wireframe)
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
else
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
handled = true;
|
|
updateGL();
|
|
}
|
|
else if ((e->key()==Qt::Key_F) && (modifiers==Qt::NoButton))
|
|
{
|
|
flatShading = !flatShading;
|
|
if (flatShading)
|
|
{
|
|
::glShadeModel(GL_FLAT);
|
|
::glDisable(GL_BLEND);
|
|
::glDisable(GL_LINE_SMOOTH);
|
|
::glDisable(GL_POLYGON_SMOOTH_HINT);
|
|
::glBlendFunc(GL_ONE, GL_ZERO);
|
|
::glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
|
|
}
|
|
else
|
|
{
|
|
::glShadeModel(GL_SMOOTH);
|
|
::glEnable(GL_BLEND);
|
|
::glEnable(GL_LINE_SMOOTH);
|
|
::glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
|
|
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
handled = true;
|
|
updateGL();
|
|
}
|
|
else if ((e->key()==Qt::Key_E) && (modifiers==Qt::NoButton))
|
|
{
|
|
edges = !edges;
|
|
handled = true;
|
|
updateGL();
|
|
}
|
|
else if ((e->key()==Qt::Key_V) && (modifiers==Qt::NoButton))
|
|
{
|
|
vertices = !vertices;
|
|
handled = true;
|
|
updateGL();
|
|
}
|
|
|
|
if (!handled)
|
|
QGLViewer::keyPressEvent(e);
|
|
}
|
|
|
|
QString Viewer::helpString() const
|
|
{
|
|
QString text("<h2>M a p V i e w e r</h2>");
|
|
text += "Use the mouse to move the camera around the object. ";
|
|
text += "You can respectively revolve around, zoom and translate with the three mouse buttons. ";
|
|
text += "Left and middle buttons pressed together rotate around the camera view direction axis<br><br>";
|
|
text += "Pressing <b>Alt</b> and one of the function keys (<b>F1</b>..<b>F12</b>) defines a camera keyFrame. ";
|
|
text += "Simply press the function key again to restore it. Several keyFrames define a ";
|
|
text += "camera path. Paths are saved when you quit the application and restored at next start.<br><br>";
|
|
text += "Press <b>F</b> to display the frame rate, <b>A</b> for the world axis, ";
|
|
text += "<b>Alt+Return</b> for full screen mode and <b>Control+S</b> to save a snapshot. ";
|
|
text += "See the <b>Keyboard</b> tab in this window for a complete shortcut list.<br><br>";
|
|
text += "Double clicks automates single click actions: A left button double click aligns the closer axis with the camera (if close enough). ";
|
|
text += "A middle button double click fits the zoom of the camera and the right button re-centers the scene.<br><br>";
|
|
text += "A left button double click while holding right button pressed defines the camera <i>Revolve Around Point</i>. ";
|
|
text += "See the <b>Mouse</b> tab and the documentation web pages for details.<br><br>";
|
|
text += "Press <b>Escape</b> to exit the viewer.";
|
|
return text;
|
|
}
|
|
|
|
#include "Viewer.moc"
|