Merge pull request #3488 from gdamiand/LCC_demo-gdamiand

LCC demo
This commit is contained in:
Laurent Rineau 2018-12-10 14:38:20 +01:00
commit 1813a1ca45
7 changed files with 361 additions and 1069 deletions

View File

@ -426,25 +426,7 @@ public:
const Local_point& S=facet[id];
const Local_point& T=facet[(id+1==facet.size())?0:id+1];
Local_vector V1=Local_vector((T-S).x(), (T-S).y(), (T-S).z());
if(std::isnan(S.x()) ||
std::isnan(S.y()) ||
std::isnan(S.z()))
{
return false;
}
if(std::isnan(T.x()) ||
std::isnan(T.y()) ||
std::isnan(T.z()))
{
return false;
}
const Local_point& U=facet[(id+2==facet.size())?0:id+2];
if(std::isnan(U.x()) ||
std::isnan(U.y()) ||
std::isnan(U.z()))
{
return false;
}
const Local_point& U=facet[(id+2>=facet.size())?id+2-facet.size():id+2];
Local_vector V2=Local_vector((U-T).x(), (U-T).y(), (U-T).z());
orientation = Local_kernel::Orientation_3()(V1, V2, normal);
@ -465,7 +447,7 @@ public:
const Local_point& T=facet[(id+1==facet.size())?0:id+1];
Local_vector V1=Local_vector((T-S).x(), (T-S).y(), (T-S).z());
const Local_point& U=facet[(id+2==facet.size())?0:id+2];
const Local_point& U=facet[(id+2>=facet.size())?id+2-facet.size():id+2];
Local_vector V2=Local_vector((U-T).x(), (U-T).y(), (U-T).z());
local_orientation=Local_kernel::Orientation_3()(V1, V2, normal) ;

View File

@ -740,7 +740,7 @@ protected:
setKeyDescription(::Qt::Key_E, "Toggles edges display");
setKeyDescription(::Qt::Key_F, "Toggles faces display");
setKeyDescription(::Qt::Key_G, "Switch between flat/Gouraud shading display");
setKeyDescription(::Qt::Key_M, "Toggles mono color for all faces");
setKeyDescription(::Qt::Key_M, "Toggles mono color");
setKeyDescription(::Qt::Key_N, "Inverse direction of normals");
setKeyDescription(::Qt::Key_V, "Toggles vertices display");
setKeyDescription(::Qt::Key_Plus, "Increase size of edges");
@ -935,8 +935,11 @@ protected:
}
virtual QString helpString() const
{ return helpString("CGAL Basic Viewer"); }
virtual QString helpString(const char* title) const
{
QString text("<h2>C G A L B a s i c V i e w e r</h2>");
QString text(QString("<h2>")+QString(title)+QString("</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. ";
@ -966,7 +969,7 @@ protected:
return text;
}
private:
protected:
bool m_draw_vertices;
bool m_draw_edges;
bool m_draw_faces;

View File

@ -46,7 +46,7 @@ if ( NOT (CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND ) )
else()
add_definitions(-DQT_NO_KEYWORDS)
add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS)
# ui file, created wih Qt Designer
qt5_wrap_ui(uis MainWindow.ui CreateMesh.ui CreateMenger.ui
@ -64,7 +64,7 @@ add_executable(Linear_cell_complex_3_demo
add_to_cached_list(CGAL_EXECUTABLE_TARGETS Linear_cell_complex_3_demo)
target_link_libraries(Linear_cell_complex_3_demo PRIVATE
target_link_libraries(Linear_cell_complex_3_demo PUBLIC
CGAL::CGAL CGAL::CGAL_Qt5 Qt5::Gui Qt5::OpenGL)
include(${CGAL_MODULES_DIR}/CGAL_add_test.cmake)

View File

@ -39,7 +39,7 @@ void subdivide_lcc_pqq (LCC & m);
#define DELAY_STATUSMSG 1500
MainWindow::MainWindow (QWidget * parent):CGAL::Qt::DemosMainWindow (parent),
MainWindow::MainWindow (QWidget * parent) : CGAL::Qt::DemosMainWindow (parent),
nbcube (0),
dialogmesh (this),
dialogmenger(this),
@ -78,7 +78,7 @@ MainWindow::MainWindow (QWidget * parent):CGAL::Qt::DemosMainWindow (parent),
QObject::connect(&dialogmesh, SIGNAL(accepted()),
this, SLOT(onCreateMeshOk()));
this->viewer->setScene(&scene);
this->viewer->setScene(&scene, false);
connect_actions ();
this->addAboutDemo (":/cgal/help/about_Linear_cell_complex_3.html");

View File

@ -19,928 +19,44 @@
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
// Contributor(s): Kumar Snehasish <kumar.snehasish@gmail.com>
//
#include "Viewer.h"
#include <CGAL/Linear_cell_complex_operations.h>
#include <CGAL/bounding_box.h>
#include <CGAL/Qt/CreateOpenGLContext.h>
#include <CGAL/Qt/viewer_actions.h>
#include <CGAL/Qt/vec.h>
#include <QDebug>
//Vertex source code
const char vertex_source[] =
{
"#version 120 \n"
"attribute highp vec4 vertex;\n"
"attribute highp vec3 normal;\n"
"attribute highp vec3 color;\n"
Viewer::Viewer(QWidget* parent) :
Base(parent, NULL, ""),
m_previous_scene_empty(true)
{}
"uniform highp mat4 mvp_matrix;\n"
"uniform highp mat4 mv_matrix; \n"
"uniform highp float point_size; \n"
"varying highp vec4 fP; \n"
"varying highp vec3 fN; \n"
"varying highp vec4 fColor; \n"
"void main(void)\n"
"{\n"
" gl_PointSize = point_size; \n"
" fP = mv_matrix * vertex; \n"
" fN = mat3(mv_matrix)* normal; \n"
" fColor = vec4(color, 1.0); \n"
" gl_Position = mvp_matrix * vertex;\n"
"}"
};
//Vertex source code
const char fragment_source[] =
{
"#version 120 \n"
"varying highp vec4 fP; \n"
"varying highp vec3 fN; \n"
"varying highp vec4 fColor; \n"
"uniform vec4 light_pos; \n"
"uniform vec4 light_diff; \n"
"uniform vec4 light_spec; \n"
"uniform vec4 light_amb; \n"
"uniform float spec_power ; \n"
"void main(void) { \n"
" vec3 L = light_pos.xyz - fP.xyz; \n"
" vec3 V = -fP.xyz; \n"
" vec3 N = normalize(fN); \n"
" L = normalize(L); \n"
" V = normalize(V); \n"
" vec3 R = reflect(-L, N); \n"
" vec4 diffuse = max(dot(N,L), 0.0) * light_diff * fColor; \n"
" vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; \n"
"gl_FragColor = light_amb*fColor + diffuse ; \n"
"} \n"
"\n"
};
//Vertex source code
const char vertex_source_p_l[] =
{
"#version 120 \n"
"attribute highp vec4 vertex;\n"
"uniform highp mat4 mvp_matrix;\n"
"uniform highp float point_size; \n"
"void main(void)\n"
"{\n"
" gl_PointSize = point_size; \n"
" gl_Position = mvp_matrix * vertex;\n"
"}"
};
//Vertex source code
const char fragment_source_p_l[] =
{
"#version 120 \n"
"uniform highp vec4 color; \n"
"void main(void) { \n"
"gl_FragColor = color; \n"
"} \n"
"\n"
};
Viewer::Viewer(QWidget* parent)
: CGAL::QGLViewer(parent),
wireframe(false),
flatShading(true),
edges(true),
vertices(true),
inverse_normal(false),
size_points(7.),
size_edges(3.1),
ambient(0.6f, 0.5f, 0.5f, 0.5f),
m_previous_scene_empty(true),
are_buffers_initialized(false)
void Viewer::setScene(Scene* scene_, bool doredraw)
{
}
Viewer::~Viewer()
{
for (int i=0; i<NB_VBO_BUFFERS; ++i)
buffers[i].destroy();
for (int i=0; i<NB_VAO_BUFFERS; ++i)
vao[i].destroy();
}
void Viewer::compile_shaders()
{
rendering_program.removeAllShaders();
rendering_program_p_l.removeAllShaders();
// Create the buffers
for (int i=0; i<NB_VBO_BUFFERS; ++i)
if(!buffers[i].isCreated() && !buffers[i].create())
{
std::cerr<<"VBO Creation number "<<i<<" FAILED"<<std::endl;
}
for (int i=0; i<NB_VAO_BUFFERS; ++i)
if(!vao[i].isCreated() && !vao[i].create())
{
std::cerr<<"VAO Creation number "<<i<<" FAILED"<<std::endl;
}
//The Facets
QOpenGLShader *vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex);
if(!vertex_shader->compileSourceCode(vertex_source))
{
std::cerr<<"Compiling vertex source FAILED"<<std::endl;
}
QOpenGLShader *fragment_shader= new QOpenGLShader(QOpenGLShader::Fragment);
if(!fragment_shader->compileSourceCode(fragment_source))
{
std::cerr<<"Compiling fragmentsource FAILED"<<std::endl;
}
if(!rendering_program.addShader(vertex_shader))
{
std::cerr<<"adding vertex shader FAILED"<<std::endl;
}
if(!rendering_program.addShader(fragment_shader))
{
std::cerr<<"adding fragment shader FAILED"<<std::endl;
}
if(!rendering_program.link())
{
std::cerr<<"linking Program FAILED"<<std::endl;
}
rendering_program.bind();
vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex);
if(!vertex_shader->compileSourceCode(vertex_source_p_l))
{
std::cerr<<"Compiling vertex source FAILED"<<std::endl;
}
fragment_shader= new QOpenGLShader(QOpenGLShader::Fragment);
if(!fragment_shader->compileSourceCode(fragment_source_p_l))
{
std::cerr<<"Compiling fragmentsource FAILED"<<std::endl;
}
if(!rendering_program_p_l.addShader(vertex_shader))
{
std::cerr<<"adding vertex shader FAILED"<<std::endl;
}
if(!rendering_program_p_l.addShader(fragment_shader))
{
std::cerr<<"adding fragment shader FAILED"<<std::endl;
}
if(!rendering_program_p_l.link())
{
std::cerr<<"linking Program FAILED"<<std::endl;
}
rendering_program_p_l.bind();
}
void Viewer::initialize_buffers()
{
//points of the facets
vao[0].bind();
buffers[0].bind();
buffers[0].allocate(pos_facets.data(),
static_cast<int>(pos_facets.size()*sizeof(float)));
vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.bind();
rendering_program.enableAttributeArray(vertexLocation[0]);
rendering_program.setAttributeBuffer(vertexLocation[0],GL_FLOAT,0,3);
rendering_program.release();
buffers[0].release();
//normals of the facets
buffers[1].bind();
buffers[1].allocate(flat_normals.data(),
static_cast<int>(flat_normals.size()*sizeof(float)));
normalsLocation = rendering_program.attributeLocation("normal");
rendering_program.bind();
rendering_program.enableAttributeArray(normalsLocation);
rendering_program.setAttributeBuffer(normalsLocation,GL_FLOAT,0,3);
buffers[1].release();
//colors of the facets
buffers[2].bind();
buffers[2].allocate(colors.data(),
static_cast<int>(colors.size()*sizeof(float)));
colorsLocation = rendering_program.attributeLocation("color");
rendering_program.bind();
rendering_program.enableAttributeArray(colorsLocation);
rendering_program.setAttributeBuffer(colorsLocation,GL_FLOAT,0,3);
buffers[2].release();
rendering_program.release();
vao[0].release();
vao[1].bind();
//points of the facets
buffers[3].bind();
buffers[3].allocate(pos_facets.data(), static_cast<int>(pos_facets.size()*sizeof(float)));
vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.bind();
rendering_program.enableAttributeArray(vertexLocation[0]);
rendering_program.setAttributeBuffer(vertexLocation[0],GL_FLOAT,0,3);
rendering_program.release();
buffers[3].release();
//normals of the facets
buffers[4].bind();
buffers[4].allocate(smooth_normals.data(),
static_cast<int>(smooth_normals.size()*sizeof(float)));
normalsLocation = rendering_program.attributeLocation("normal");
rendering_program.bind();
rendering_program.enableAttributeArray(normalsLocation);
rendering_program.setAttributeBuffer(normalsLocation,GL_FLOAT,0,3);
buffers[4].release();
//colors of the facets
buffers[5].bind();
buffers[5].allocate(colors.data(), static_cast<int>(colors.size()*sizeof(float)));
colorsLocation = rendering_program.attributeLocation("color");
rendering_program.bind();
rendering_program.enableAttributeArray(colorsLocation);
rendering_program.setAttributeBuffer(colorsLocation,GL_FLOAT,0,3);
buffers[5].release();
rendering_program.release();
vao[1].release();
//The lines
vao[2].bind();
buffers[6].bind();
buffers[6].allocate(pos_lines.data(), static_cast<int>(pos_lines.size()*sizeof(float)));
vertexLocation[2] = rendering_program_p_l.attributeLocation("vertex");
rendering_program_p_l.bind();
rendering_program_p_l.enableAttributeArray(vertexLocation[2]);
rendering_program_p_l.setAttributeBuffer(vertexLocation[2],GL_FLOAT,0,3);
buffers[6].release();
rendering_program_p_l.release();
vao[2].release();
//The points
vao[3].bind();
buffers[7].bind();
buffers[7].allocate(pos_points.data(), static_cast<int>(pos_points.size()*sizeof(float)));
vertexLocation[2] = rendering_program_p_l.attributeLocation("vertex");
rendering_program_p_l.bind();
rendering_program_p_l.enableAttributeArray(vertexLocation[2]);
rendering_program_p_l.setAttributeBuffer(vertexLocation[2],GL_FLOAT,0,3);
buffers[7].release();
rendering_program_p_l.release();
vao[3].release();
are_buffers_initialized = true;
}
void Viewer::compute_face(Dart_handle dh, LCC::size_type markface)
{
LCC &lcc = *scene->lcc;
CGAL::mark_cell<LCC, 2>(lcc, dh, markface);
double r = (double)lcc.info<3>(dh).color().r()/255.0;
double g = (double)lcc.info<3>(dh).color().g()/255.0;
double b = (double)lcc.info<3>(dh).color().b()/255.0;
if ( !lcc.is_free(dh, 3) )
{
r += (double)lcc.info<3>(lcc.beta(dh,3)).color().r()/255.0;
g += (double)lcc.info<3>(lcc.beta(dh,3)).color().g()/255.0;
b += (double)lcc.info<3>(lcc.beta(dh,3)).color().b()/255.0;
r /= 2; g /= 2; b /= 2;
}
//compute flat normals
LCC::Vector normal = CGAL::compute_normal_of_cell_2(lcc,dh);
normal = normal/(CGAL::sqrt(normal*normal));
if (inverse_normal)
normal=normal*-1;
if (lcc.beta<1,1,1>(dh)!=dh)
{
try // Try catch to avoir crash of triangulation
{
P_traits cdt_traits(normal);
CDT cdt(cdt_traits);
// Iterates on the vector of facet handles
CDT::Vertex_handle previous = NULL, first = NULL;
for (LCC::Dart_of_orbit_range<1>::const_iterator
he_circ = lcc.darts_of_orbit<1>(dh).begin(),
he_circ_end = lcc.darts_of_orbit<1>(dh).end();
he_circ!=he_circ_end; ++he_circ)
{
CDT::Vertex_handle vh = cdt.insert(lcc.point(he_circ));
if(first == NULL)
{ first = vh; }
vh->info().v = CGAL::compute_normal_of_cell_0<LCC>(lcc, he_circ);
if (inverse_normal) vh->info().v=vh->info().v*-1;
if(previous!=NULL && previous != vh)
{ cdt.insert_constraint(previous, vh); }
previous = vh;
}
if (previous!=NULL)
cdt.insert_constraint(previous, first);
// sets mark is_external
for(CDT::All_faces_iterator fit = cdt.all_faces_begin(),
fitend = cdt.all_faces_end(); fit!=fitend; ++fit)
{
fit->info().is_external = true;
fit->info().is_process = false;
}
//check if the facet is external or internal
std::queue<CDT::Face_handle> face_queue;
CDT::Face_handle face_internal = NULL;
face_queue.push(cdt.infinite_vertex()->face());
while(! face_queue.empty() )
{
CDT::Face_handle fh = face_queue.front();
face_queue.pop();
if(!fh->info().is_process)
{
fh->info().is_process = true;
for(int i = 0; i <3; ++i)
{
if(!cdt.is_constrained(std::make_pair(fh, i)))
{
face_queue.push(fh->neighbor(i));
}
else if (face_internal==NULL)
{
face_internal = fh->neighbor(i);
}
}
}
}
if ( face_internal!=NULL )
face_queue.push(face_internal);
while(! face_queue.empty() )
{
CDT::Face_handle fh = face_queue.front();
face_queue.pop();
if(!fh->info().is_process)
{
fh->info().is_process = true;
fh->info().is_external = false;
for(int i = 0; i <3; ++i)
{
if(!cdt.is_constrained(std::make_pair(fh, i)))
{
face_queue.push(fh->neighbor(i));
}
}
}
}
//iterates on the internal faces to add the vertices to the positions
//and the normals to the appropriate vectors
for(CDT::Finite_faces_iterator ffit = cdt.finite_faces_begin(),
ffitend = cdt.finite_faces_end(); ffit != ffitend; ++ffit)
{
if(!ffit->info().is_external)
{
flat_normals.push_back(normal.x());
flat_normals.push_back(normal.y());
flat_normals.push_back(normal.z());
flat_normals.push_back(normal.x());
flat_normals.push_back(normal.y());
flat_normals.push_back(normal.z());
flat_normals.push_back(normal.x());
flat_normals.push_back(normal.y());
flat_normals.push_back(normal.z());
smooth_normals.push_back(ffit->vertex(0)->info().v.x());
smooth_normals.push_back(ffit->vertex(0)->info().v.y());
smooth_normals.push_back(ffit->vertex(0)->info().v.z());
smooth_normals.push_back(ffit->vertex(1)->info().v.x());
smooth_normals.push_back(ffit->vertex(1)->info().v.y());
smooth_normals.push_back(ffit->vertex(1)->info().v.z());
smooth_normals.push_back(ffit->vertex(2)->info().v.x());
smooth_normals.push_back(ffit->vertex(2)->info().v.y());
smooth_normals.push_back(ffit->vertex(2)->info().v.z());
pos_facets.push_back(ffit->vertex(0)->point().x());
pos_facets.push_back(ffit->vertex(0)->point().y());
pos_facets.push_back(ffit->vertex(0)->point().z());
pos_facets.push_back(ffit->vertex(1)->point().x());
pos_facets.push_back(ffit->vertex(1)->point().y());
pos_facets.push_back(ffit->vertex(1)->point().z());
pos_facets.push_back(ffit->vertex(2)->point().x());
pos_facets.push_back(ffit->vertex(2)->point().y());
pos_facets.push_back(ffit->vertex(2)->point().z());
colors.push_back(r);colors.push_back(g);colors.push_back(b);
colors.push_back(r);colors.push_back(g);colors.push_back(b);
colors.push_back(r);colors.push_back(g);colors.push_back(b);
}
}
}
catch(...)
{ // Triangulation crash: the face is not filled
}
}
else
{ // The face is a triangle
colors.push_back(r);colors.push_back(g);colors.push_back(b);
colors.push_back(r);colors.push_back(g);colors.push_back(b);
colors.push_back(r);colors.push_back(g);colors.push_back(b);
flat_normals.push_back(normal.x());
flat_normals.push_back(normal.y());
flat_normals.push_back(normal.z());
flat_normals.push_back(normal.x());
flat_normals.push_back(normal.y());
flat_normals.push_back(normal.z());
flat_normals.push_back(normal.x());
flat_normals.push_back(normal.y());
flat_normals.push_back(normal.z());
for (LCC::Dart_of_orbit_range<1>::const_iterator
orbitIter = lcc.darts_of_orbit<1>(dh).begin();
orbitIter.cont(); ++orbitIter)
{
//compute Smooth normals
LCC::Vector normal = CGAL::compute_normal_of_cell_0(lcc,orbitIter);
normal = normal/(CGAL::sqrt(normal*normal));
if (inverse_normal) normal=normal*-1;
smooth_normals.push_back(normal.x());
smooth_normals.push_back(normal.y());
smooth_normals.push_back(normal.z());
const LCC::Point& p = lcc.point(orbitIter);
pos_facets.push_back(p.x());
pos_facets.push_back(p.y());
pos_facets.push_back(p.z());
}
}
}
void Viewer::compute_edge(Dart_handle dh, LCC::size_type markedge)
{
LCC &lcc = *scene->lcc;
CGAL::mark_cell<LCC, 1>(lcc, dh, markedge);
const LCC::Point& p = lcc.point(dh);
Dart_handle d2 = lcc.other_extremity(dh);
if ( d2!=NULL )
{
const LCC::Point& p2 = lcc.point(d2);
pos_lines.push_back(p.x());
pos_lines.push_back(p.y());
pos_lines.push_back(p.z());
pos_lines.push_back(p2.x());
pos_lines.push_back(p2.y());
pos_lines.push_back(p2.z());
}
}
void Viewer::compute_vertex(Dart_handle dh, LCC::size_type markvertex, bool& empty)
{
LCC &lcc = *scene->lcc;
CGAL::mark_cell<LCC, 0>(lcc, dh, markvertex);
const LCC::Point& p = lcc.point(dh);
pos_points.push_back(p.x());
pos_points.push_back(p.y());
pos_points.push_back(p.z());
if ( empty )
{
bb = p.bbox();
empty = false;
}
else
bb = bb + p.bbox();
}
void Viewer::compute_elements()
{
LCC &lcc = *scene->lcc;
pos_facets.clear();
flat_normals.clear();
smooth_normals.clear();
colors.clear();
pos_lines.clear();
pos_points.clear();
if ( lcc.is_empty() )
{
bb = LCC::Point(CGAL::ORIGIN).bbox();
bb = bb + LCC::Point(1,1,1).bbox(); // To avoid a warning from Qglviewer
return;
}
LCC::size_type markvertex = lcc.get_new_mark();
LCC::size_type markedge = lcc.get_new_mark();
LCC::size_type markface = lcc.get_new_mark();
bool empty = true;
for (LCC::Attribute_range<3>::type::iterator it=lcc.attributes<3>().begin(),
itend=lcc.attributes<3>().end(); it!=itend; ++it )
{
if ( it->info().is_visible() )
{
for(LCC::Dart_of_cell_range<3>::iterator
dartIter=lcc.darts_of_cell<3>(lcc.dart_of_attribute<3>(it)).begin();
dartIter.cont(); ++dartIter)
{
if ( it->info().is_filled() && !lcc.is_marked(dartIter, markface) )
compute_face(dartIter, markface);
if ( !lcc.is_marked(dartIter, markedge) )
compute_edge(dartIter, markedge);
if ( !lcc.is_marked(dartIter, markvertex) )
compute_vertex(dartIter, markvertex, empty);
}
}
}
if ( empty )
{
bb = LCC::Point(CGAL::ORIGIN).bbox();
bb = bb + LCC::Point(1,1,1).bbox(); // To avoid a warning from Qglviewer
}
for (LCC::Dart_range::iterator it=lcc.darts().begin(),
itend=lcc.darts().end(); it!=itend; ++it )
{
lcc.unmark(it, markvertex);
lcc.unmark(it, markedge);
lcc.unmark(it, markface);
}
lcc.free_mark(markvertex);
lcc.free_mark(markedge);
lcc.free_mark(markface);
}
void Viewer::attrib_buffers(CGAL::QGLViewer* viewer)
{
QMatrix4x4 mvpMatrix;
QMatrix4x4 mvMatrix;
double mat[16];
viewer->camera()->getModelViewProjectionMatrix(mat);
for(int i=0; i < 16; i++)
{
mvpMatrix.data()[i] = (float)mat[i];
}
viewer->camera()->getModelViewMatrix(mat);
for(int i=0; i < 16; i++)
{
mvMatrix.data()[i] = (float)mat[i];
}
// define material
QVector4D diffuse( 0.9f,
0.9f,
0.9f,
0.9f );
QVector4D specular( 0.0f,
0.0f,
0.0f,
1.0f );
QVector4D position((bb.xmax()-bb.xmin())/2, (bb.ymax()-bb.ymin())/2,bb.zmax(), 0.0 );
GLfloat shininess = 1.0f;
rendering_program.bind();
mvpLocation[0] = rendering_program.uniformLocation("mvp_matrix");
mvLocation = rendering_program.uniformLocation("mv_matrix");
lightLocation[0] = rendering_program.uniformLocation("light_pos");
lightLocation[1] = rendering_program.uniformLocation("light_diff");
lightLocation[2] = rendering_program.uniformLocation("light_spec");
lightLocation[3] = rendering_program.uniformLocation("light_amb");
lightLocation[4] = rendering_program.uniformLocation("spec_power");
rendering_program.setUniformValue(lightLocation[0], position);
rendering_program.setUniformValue(lightLocation[1], diffuse);
rendering_program.setUniformValue(lightLocation[2], specular);
rendering_program.setUniformValue(lightLocation[3], ambient);
rendering_program.setUniformValue(lightLocation[4], shininess);
rendering_program.setUniformValue(mvpLocation[0], mvpMatrix);
rendering_program.setUniformValue(mvLocation, mvMatrix);
rendering_program.release();
rendering_program_p_l.bind();
mvpLocation[1] = rendering_program_p_l.uniformLocation("mvp_matrix");
colorLocation = rendering_program_p_l.uniformLocation("color");
rendering_program.setUniformValue(mvpLocation[1], mvpMatrix);
rendering_program_p_l.release();
scene = scene_;
set_lcc(scene->lcc, doredraw);
}
void Viewer::sceneChanged()
{
compute_elements();
this->camera()->setSceneBoundingBox(CGAL::qglviewer::Vec(bb.xmin(),
bb.ymin(),
bb.zmin()),
CGAL::qglviewer::Vec(bb.xmax(),
bb.ymax(),
bb.zmax()));
are_buffers_initialized = false;
Base::compute_elements();
this->camera()->
setSceneBoundingBox(CGAL::qglviewer::Vec(m_bounding_box.xmin(),
m_bounding_box.ymin(),
m_bounding_box.zmin()),
CGAL::qglviewer::Vec(m_bounding_box.xmax(),
m_bounding_box.ymax(),
m_bounding_box.zmax()));
Base::redraw();
if (m_previous_scene_empty)
this->showEntireScene();
else
this->update();
{ this->showEntireScene(); }
m_previous_scene_empty = scene->lcc->is_empty(); // for the next call to sceneChanged
}
void Viewer::draw()
{
if(scene)
{
glEnable(GL_DEPTH_TEST);
if(!are_buffers_initialized)
initialize_buffers();
QColor color;
if ( !wireframe )
{
if(flatShading)
{
vao[0].bind();
attrib_buffers(this);
rendering_program.bind();
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(pos_facets.size()/3));
rendering_program.release();
vao[0].release();
}
else
{
vao[1].bind();
attrib_buffers(this);
rendering_program.bind();
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(pos_facets.size()/3));
rendering_program.release();
vao[1].release();
}
}
if(edges)
{
vao[2].bind();
attrib_buffers(this);
color.setRgbF(0.2f, 0.2f, 0.7f);
rendering_program_p_l.bind();
rendering_program_p_l.setAttributeValue(colorLocation,color);
glLineWidth(size_edges);
glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(pos_lines.size()/3));
rendering_program_p_l.release();
vao[2].release();
}
if(vertices)
{
vao[3].bind();
attrib_buffers(this);
color.setRgbF(.2f,.2f,.6f);
rendering_program_p_l.bind();
rendering_program_p_l.setAttributeValue(colorLocation,color);
rendering_program_p_l.setUniformValue("point_size", GLfloat(size_points));
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(pos_points.size()/3));
rendering_program_p_l.release();
vao[3].release();
}
}
}
void Viewer::init()
{
// Restore previous viewer state.
restoreStateFromFile();
initializeOpenGLFunctions();
// Define 'Control+Q' as the new exit shortcut (default was 'Escape')
setShortcut(CGAL::qglviewer::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");
setKeyDescription(Qt::Key_N, "Inverse direction of normals");
setKeyDescription(Qt::Key_Plus, "Increase size of edges");
setKeyDescription(Qt::Key_Minus, "Decrease size of edges");
setKeyDescription(Qt::Key_Plus+Qt::ShiftModifier, "Increase size of vertices");
setKeyDescription(Qt::Key_Minus+Qt::ShiftModifier, "Decrease size of vertices");
setKeyDescription(Qt::Key_PageDown, "Increase light (all colors, use shift/alt/ctrl for one rgb component)");
setKeyDescription(Qt::Key_PageUp, "Decrease light (all colors, use shift/alt/ctrl for one rgb component)");
// Light default parameters
glLineWidth(size_edges);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0f,1.0f);
glClearColor(1.0f,1.0f,1.0f,0.0f);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_POLYGON_SMOOTH_HINT);
glBlendFunc(GL_ONE, GL_ZERO);
glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
compile_shaders();
}
void Viewer::keyPressEvent(QKeyEvent *e)
{
const Qt::KeyboardModifiers modifiers = e->modifiers();
if ((e->key()==Qt::Key_W) && (modifiers==Qt::NoButton))
{
wireframe = !wireframe;
if (wireframe)
{
displayMessage("Wireframe.");
}
else
{
displayMessage("Filled faces.");
}
update();
}
else if ((e->key()==Qt::Key_F) && (modifiers==Qt::NoButton))
{
flatShading = !flatShading;
if (flatShading)
displayMessage("Flat shading.");
else
displayMessage("Gouraud shading.");
update();
}
else if ((e->key()==Qt::Key_E) && (modifiers==Qt::NoButton))
{
edges = !edges;
displayMessage(QString("Draw edges=%1.").arg(edges?"true":"false"));
update();
}
else if ((e->key()==Qt::Key_V) && (modifiers==Qt::NoButton))
{
vertices = !vertices;
displayMessage(QString("Draw vertices=%1.").arg(vertices?"true":"false"));
update();
}
else if ((e->key()==Qt::Key_N) && (modifiers==Qt::NoButton))
{
inverse_normal = !inverse_normal;
displayMessage(QString("Inverse normal=%1.").arg(inverse_normal?"true":"false"));
sceneChanged();
}
else if ((e->key()==Qt::Key_Plus) && (modifiers==Qt::KeypadModifier))
{
size_edges+=.5;
displayMessage(QString("Size of edges=%1.").arg(size_edges));
update();
}
else if ((e->key()==Qt::Key_Minus) && (modifiers==Qt::KeypadModifier))
{
if (size_edges>.5) size_edges-=.5;
displayMessage(QString("Size of edges=%1.").arg(size_edges));
update();
}
else if ((e->key()==Qt::Key_Plus) && (modifiers==(Qt::ShiftModifier|Qt::KeypadModifier)))
{
size_points+=.5;
displayMessage(QString("Size of points=%1.").arg(size_points));
update();
}
else if ((e->key()==Qt::Key_Minus) && (modifiers==(Qt::ShiftModifier|Qt::KeypadModifier)))
{
if (size_points>.5) size_points-=.5;
displayMessage(QString("Size of points=%1.").arg(size_points));
update();
}
else if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton))
{
ambient.setX(ambient.x()+.1);
if (ambient.x()>1.) ambient.setX(1.);
ambient.setY(ambient.x()+.1);
if (ambient.y()>1.) ambient.setY(1.);
ambient.setZ(ambient.x()+.1);
if (ambient.z()>1.) ambient.setZ(1.);
displayMessage(QString("Light color=(%1 %2 %3).").
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
update();
}
else if ((e->key()==Qt::Key_PageDown) && (modifiers==Qt::NoButton))
{
ambient.setX(ambient.x()-.1);
if (ambient.x()<0.) ambient.setX(0.);
ambient.setY(ambient.y()-.1);
if (ambient.y()<0.) ambient.setY(0.);
ambient.setZ(ambient.z()-.1);
if (ambient.z()<0.) ambient.setZ(0.);
displayMessage(QString("Light color=(%1 %2 %3).").
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
update();
}
else if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::ShiftModifier))
{
ambient.setX(ambient.x()+.1);
if (ambient.x()>1.) ambient.setX(1.);
displayMessage(QString("Light color=(%1 %2 %3).").
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
update();
}
else if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::AltModifier))
{
ambient.setY(ambient.y()+.1);
if (ambient.y()>1.) ambient.setY(1.);
displayMessage(QString("Light color=(%1 %2 %3).").
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
update();
}
else if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::ControlModifier))
{
ambient.setZ(ambient.z()+.1);
if (ambient.z()>1.) ambient.setZ(1.);
displayMessage(QString("Light color=(%1 %2 %3).").
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
update();
}
else if ((e->key()==Qt::Key_PageDown) && (modifiers==Qt::ShiftModifier))
{
ambient.setX(ambient.x()-.1);
if (ambient.x()<0.) ambient.setX(0.);
displayMessage(QString("Light color=(%1 %2 %3).").
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
update();
}
else if ((e->key()==Qt::Key_PageDown) && (modifiers==Qt::AltModifier))
{
ambient.setY(ambient.y()-.1);
if (ambient.y()<0.) ambient.setY(0.);
displayMessage(QString("Light color=(%1 %2 %3).").
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
update();
}
else if ((e->key()==Qt::Key_PageDown) && (modifiers==Qt::ControlModifier))
{
ambient.setZ(ambient.z()-.1);
if (ambient.z()<0.) ambient.setZ(0.);
displayMessage(QString("Light color=(%1 %2 %3).").
arg(ambient.x()).arg(ambient.y()).arg(ambient.z()));
update();
}
else
CGAL::QGLViewer::keyPressEvent(e);
// const Qt::KeyboardModifiers modifiers = e->modifiers();
Base::keyPressEvent(e);
}
QString Viewer::helpString() const
{
QString text("<h2>L C C 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;
}
{ return Base::helpString("LCC Demo"); }

View File

@ -23,96 +23,114 @@
#define VIEWER_H
#include "typedefs.h"
#include <CGAL/draw_linear_cell_complex.h>
#include <vector>
#include <QMap>
#include <CGAL/Qt/qglviewer.h>
#include <QKeyEvent>
#include <QOpenGLFunctions_2_1>
#include <QOpenGLVertexArrayObject>
#include <QGLBuffer>
#include <QOpenGLShaderProgram>
// Functor used by SimpleLCCViewerQt to colorize of not elements.
struct MyDrawingFunctorLCC
{
/// @return true iff the volume containing dh is drawn.
template<typename LCC>
bool draw_volume(const LCC& alcc,
typename LCC::Dart_const_handle dh) const
{ return alcc.template info<3>(dh).is_visible(); }
/// @return true iff the face containing dh is drawn.
template<typename LCC>
bool draw_face(const LCC&,
typename LCC::Dart_const_handle) const
{ return true; }
/// @return true iff the edge containing dh is drawn.
template<typename LCC>
bool draw_edge(const LCC&,
typename LCC::Dart_const_handle) const
{ return true; }
/// @return true iff the vertex containing dh is drawn.
template<typename LCC>
bool draw_vertex(const LCC&,
typename LCC::Dart_const_handle) const
{ return true; }
#define NB_VBO_BUFFERS 8
#define NB_VAO_BUFFERS 4
/// @return true iff the volume containing dh is drawn in wireframe.
template<typename LCC>
bool volume_wireframe(const LCC& alcc,
typename LCC::Dart_const_handle dh) const
{ return !(alcc.template info<3>(dh).is_filled()); }
/// @return true iff the face containing dh is drawn in wireframe.
template<typename LCC>
bool face_wireframe(const LCC&,
typename LCC::Dart_const_handle) const
{ return false; }
class Viewer : public CGAL::QGLViewer
/// @return true iff the volume containing dh is colored.
template<typename LCC>
bool colored_volume(const LCC&,
typename LCC::Dart_const_handle) const
{ return true; }
/// @return true iff the face containing dh is colored.
/// if we have also colored_volume(alcc, dh), the volume color is
/// ignored and only the face color is considered.
template<typename LCC>
bool colored_face(const LCC&,
typename LCC::Dart_const_handle) const
{ return false; }
/// @return true iff the edge containing dh is colored.
template<typename LCC>
bool colored_edge(const LCC&,
typename LCC::Dart_const_handle) const
{ return false; }
/// @return true iff the vertex containing dh is colored.
template<typename LCC>
bool colored_vertex(const LCC&,
typename LCC::Dart_const_handle) const
{ return false; }
/// @return the color of the volume containing dh
/// used only if colored_volume(alcc, dh) and !colored_face(alcc, dh)
template<typename LCC>
CGAL::Color volume_color(const LCC& alcc,
typename LCC::Dart_const_handle dh) const
{ return alcc.template info<3>(dh).color(); }
/// @return the color of the face containing dh
/// used only if colored_face(alcc, dh)
template<typename LCC>
CGAL::Color face_color(const LCC& alcc,
typename LCC::Dart_const_handle dh) const
{
CGAL::Random random((unsigned int)(alcc.darts().index(dh)));
return get_random_color(random);
}
/// @return the color of the edge containing dh
/// used only if colored_edge(alcc, dh)
template<typename LCC>
CGAL::Color edge_color(const LCC&,
typename LCC::Dart_const_handle) const
{ return CGAL::Color(0, 0, 0); }
/// @return the color of the vertex containing dh
/// used only if colored_vertex(alcc, dh)
template<typename LCC>
CGAL::Color vertex_color(const LCC&,
typename LCC::Dart_const_handle) const
{ return CGAL::Color(0, 0, 0); }
};
class Viewer : public CGAL::SimpleLCCViewerQt<LCC, MyDrawingFunctorLCC>
{
Q_OBJECT
typedef LCC::Dart_handle Dart_handle;
typedef LCC::Dart_const_handle Dart_const_handle;
typedef CGAL::SimpleLCCViewerQt<LCC, MyDrawingFunctorLCC> Base;
public:
Viewer(QWidget* parent);
~Viewer();
void setScene(Scene* scene_)
{ scene = scene_; }
public:
void draw();
virtual void init();
void setScene(Scene* scene_, bool doredraw=true);
void keyPressEvent(QKeyEvent *e);
virtual QString helpString() const;
public Q_SLOTS:
void sceneChanged();
private:
void initialize_buffers();
void attrib_buffers(CGAL::QGLViewer*);
void compile_shaders();
void compute_elements();
void compute_face(Dart_handle dh, LCC::size_type markface);
void compute_edge(Dart_handle dh, LCC::size_type markedge);
void compute_vertex(Dart_handle dh, LCC::size_type markvertex, bool& empty);
private:
Scene* scene;
bool wireframe;
bool flatShading;
bool edges;
bool vertices;
bool inverse_normal;
double size_points;
double size_edges;
QVector4D ambient;
bool m_previous_scene_empty;
bool are_buffers_initialized;
//Shaders elements
int vertexLocation[3];
int normalsLocation;
int mvpLocation[2];
int mvLocation;
int colorLocation;
int colorsLocation;
int lightLocation[5];
std::vector<float> pos_points;
std::vector<float> pos_lines;
std::vector<float> pos_facets;
std::vector<float> smooth_normals;
std::vector<float> flat_normals;
std::vector<float> colors;
QGLBuffer buffers[NB_VBO_BUFFERS];
QOpenGLVertexArrayObject vao[NB_VAO_BUFFERS];
QOpenGLShaderProgram rendering_program;
QOpenGLShaderProgram rendering_program_p_l;
CGAL::Bbox_3 bb;
};
#endif

View File

@ -31,15 +31,96 @@ namespace CGAL
{
// Default color functor; user can change it to have its own face color
struct DefaultColorFunctorLCC
struct DefaultDrawingFunctorLCC
{
/// @return true iff the volume containing dh is drawn.
template<typename LCC>
static CGAL::Color run(const LCC& alcc,
typename LCC::Dart_const_handle dh)
{
if (dh==alcc.null_handle) // use to get the mono color
return CGAL::Color(100, 125, 200); // R G B between 0-255
bool draw_volume(const LCC&,
typename LCC::Dart_const_handle) const
{ return true; }
/// @return true iff the face containing dh is drawn.
template<typename LCC>
bool draw_face(const LCC&,
typename LCC::Dart_const_handle) const
{ return true; }
/// @return true iff the edge containing dh is drawn.
template<typename LCC>
bool draw_edge(const LCC&,
typename LCC::Dart_const_handle) const
{ return true; }
/// @return true iff the vertex containing dh is drawn.
template<typename LCC>
bool draw_vertex(const LCC&,
typename LCC::Dart_const_handle) const
{ return true; }
/// @return true iff the volume containing dh is drawn in wireframe.
template<typename LCC>
bool volume_wireframe(const LCC&,
typename LCC::Dart_const_handle) const
{ return false; }
/// @return true iff the face containing dh is drawn in wireframe.
template<typename LCC>
bool face_wireframe(const LCC&,
typename LCC::Dart_const_handle) const
{ return false; }
/// @return true iff the volume containing dh is colored.
template<typename LCC>
bool colored_volume(const LCC&,
typename LCC::Dart_const_handle) const
{ return true; }
/// @return true iff the face containing dh is colored.
/// if we have also colored_volume(alcc, dh), the volume color is
/// ignored and only the face color is considered.
template<typename LCC>
bool colored_face(const LCC&,
typename LCC::Dart_const_handle) const
{ return false; }
/// @return true iff the edge containing dh is colored.
template<typename LCC>
bool colored_edge(const LCC&,
typename LCC::Dart_const_handle) const
{ return false; }
/// @return true iff the vertex containing dh is colored.
template<typename LCC>
bool colored_vertex(const LCC&,
typename LCC::Dart_const_handle) const
{ return false; }
/// @return the color of the volume containing dh
/// used only if colored_volume(alcc, dh) and !colored_face(alcc, dh)
template<typename LCC>
CGAL::Color volume_color(const LCC& alcc,
typename LCC::Dart_const_handle dh) const
{
CGAL::Random random((unsigned int)(alcc.darts().index(dh)));
return get_random_color(random);
}
/// @return the color of the face containing dh
/// used only if colored_face(alcc, dh)
template<typename LCC>
CGAL::Color face_color(const LCC& alcc,
typename LCC::Dart_const_handle dh) const
{
CGAL::Random random((unsigned int)(alcc.darts().index(dh)));
return get_random_color(random);
}
/// @return the color of the edge containing dh
/// used only if colored_edge(alcc, dh)
template<typename LCC>
CGAL::Color edge_color(const LCC& alcc,
typename LCC::Dart_const_handle dh) const
{
CGAL::Random random((unsigned int)(alcc.darts().index(dh)));
return get_random_color(random);
}
/// @return the color of the vertex containing dh
/// used only if colored_vertex(alcc, dh)
template<typename LCC>
CGAL::Color vertex_color(const LCC& alcc,
typename LCC::Dart_const_handle dh) const
{
CGAL::Random random((unsigned int)(alcc.darts().index(dh)));
return get_random_color(random);
}
@ -73,7 +154,7 @@ struct LCC_geom_utils<LCC, Kernel, 2>
};
// Viewer class for LCC
template<class LCC, class ColorFunctor>
template<class LCC, class DrawingFunctorLCC>
class SimpleLCCViewerQt : public Basic_viewer_qt
{
typedef Basic_viewer_qt Base;
@ -89,42 +170,68 @@ public:
/// @param anofaces if true, do not draw faces (faces are not computed; this can be
/// usefull for very big object where this time could be long)
SimpleLCCViewerQt(QWidget* parent,
const LCC& alcc,
const LCC* alcc=NULL,
const char* title="Basic LCC Viewer",
bool anofaces=false,
const ColorFunctor& fcolor=ColorFunctor()) :
const DrawingFunctorLCC& drawing_functor=DrawingFunctorLCC()) :
// First draw: vertices; edges, faces; multi-color; inverse normal
Base(parent, title, true, true, true, false, true),
lcc(alcc),
m_nofaces(anofaces),
m_fcolor(fcolor)
m_random_face_color(false),
m_drawing_functor(drawing_functor)
{
compute_elements();
}
protected:
void compute_face(Dart_const_handle dh)
void set_lcc(const LCC* alcc, bool doredraw=true)
{
lcc=alcc;
compute_elements();
if (doredraw) { redraw(); }
}
void compute_face(Dart_const_handle dh, Dart_const_handle voldh)
{
if (m_nofaces || !m_drawing_functor.draw_face(*lcc, dh)) return;
// We fill only closed faces.
Dart_const_handle cur=dh;
Dart_const_handle min=dh;
do
{
if (!lcc.is_next_exist(cur)) return; // open face=>not filled
if (!lcc->is_next_exist(cur)) return; // open face=>not filled
if (cur<min) min=cur;
cur=lcc.next(cur);
cur=lcc->next(cur);
}
while(cur!=dh);
CGAL::Color c=m_fcolor.run(lcc, dh);
face_begin(c);
if (m_random_face_color)
{
CGAL::Random random((unsigned int)(lcc->darts().index(dh)));
CGAL::Color c=get_random_color(random);
face_begin(c);
}
else if (m_drawing_functor.colored_face(*lcc, dh))
{
CGAL::Color c=m_drawing_functor.face_color(*lcc, dh);
face_begin(c);
}
else if (m_drawing_functor.colored_volume(*lcc, voldh))
{
CGAL::Color c=m_drawing_functor.volume_color(*lcc, voldh);
face_begin(c);
}
else
{ face_begin(); }
cur=dh;
do
{
add_point_in_face(lcc.point(cur), LCC_geom_utils<LCC, Local_kernel>::
get_vertex_normal(lcc, cur));
cur=lcc.next(cur);
add_point_in_face(lcc->point(cur), LCC_geom_utils<LCC, Local_kernel>::
get_vertex_normal(*lcc, cur));
cur=lcc->next(cur);
}
while(cur!=dh);
@ -133,77 +240,143 @@ protected:
void compute_edge(Dart_const_handle dh)
{
Point p1 = lcc.point(dh);
Dart_const_handle d2 = lcc.other_extremity(dh);
if (!m_drawing_functor.draw_edge(*lcc, dh)) return;
Point p1 = lcc->point(dh);
Dart_const_handle d2 = lcc->other_extremity(dh);
if (d2!=NULL)
{ add_segment(p1, lcc.point(d2)); }
{
if (m_drawing_functor.colored_edge(*lcc, dh))
{ add_segment(p1, lcc->point(d2), m_drawing_functor.edge_color(*lcc, dh)); }
else
{ add_segment(p1, lcc->point(d2)); }
}
}
void compute_vertex(Dart_const_handle dh)
{ add_point(lcc.point(dh)); }
{
if (!m_drawing_functor.draw_vertex(*lcc, dh)) return;
if (m_drawing_functor.colored_vertex(*lcc, dh))
{ add_point(lcc->point(dh), m_drawing_functor.vertex_color(*lcc, dh)); }
else
{ add_point(lcc->point(dh)); }
}
void compute_elements()
{
clear();
if (lcc==NULL) return;
typename LCC::size_type markvolumes = lcc->get_new_mark();
typename LCC::size_type markfaces = lcc->get_new_mark();
typename LCC::size_type markedges = lcc->get_new_mark();
typename LCC::size_type markvertices = lcc->get_new_mark();
typename LCC::size_type markfaces = lcc.get_new_mark();
typename LCC::size_type markedges = lcc.get_new_mark();
typename LCC::size_type markvertices = lcc.get_new_mark();
for (typename LCC::Dart_range::const_iterator it=lcc.darts().begin(),
itend=lcc.darts().end(); it!=itend; ++it )
for (typename LCC::Dart_range::const_iterator it=lcc->darts().begin(),
itend=lcc->darts().end(); it!=itend; ++it )
{
if ( !m_nofaces && !lcc.is_marked(it, markfaces) )
if (!lcc->is_marked(it, markvolumes) &&
m_drawing_functor.draw_volume(*lcc, it))
{
compute_face(it);
CGAL::mark_cell<LCC, 2>(lcc, it, markfaces);
}
if ( !lcc.is_marked(it, markedges) )
{
compute_edge(it);
CGAL::mark_cell<LCC, 1>(lcc, it, markedges);
}
if ( !lcc.is_marked(it, markvertices) )
{
compute_vertex(it);
CGAL::mark_cell<LCC, 0>(lcc, it, markvertices);
for (typename LCC::template Dart_of_cell_basic_range<3>::
const_iterator itv=lcc->template darts_of_cell_basic<3>(it, markvolumes).begin(),
itvend=lcc->template darts_of_cell_basic<3>(it, markvolumes).end();
itv!=itvend; ++itv)
{
lcc->mark(itv, markvolumes); // To be sure that all darts of the basic iterator will be marked
if (!lcc->is_marked(itv, markfaces) &&
m_drawing_functor.draw_face(*lcc, itv))
{
if (!m_drawing_functor.volume_wireframe(*lcc, itv) &&
!m_drawing_functor.face_wireframe(*lcc, itv))
{ compute_face(itv, it); }
for (typename LCC::template Dart_of_cell_basic_range<2>::
const_iterator itf=lcc->template darts_of_cell_basic<2>(itv, markfaces).begin(),
itfend=lcc->template darts_of_cell_basic<2>(itv, markfaces).end();
itf!=itfend; ++itf)
{
if (!m_drawing_functor.volume_wireframe(*lcc, itv) &&
!m_drawing_functor.face_wireframe(*lcc, itv))
{ lcc->mark(itf, markfaces); } // To be sure that all darts of the basic iterator will be marked
if ( !lcc->is_marked(itf, markedges) &&
m_drawing_functor.draw_edge(*lcc, itf))
{
compute_edge(itf);
for (typename LCC::template Dart_of_cell_basic_range<1>::
const_iterator ite=lcc->template darts_of_cell_basic<1>(itf, markedges).begin(),
iteend=lcc->template darts_of_cell_basic<1>(itf, markedges).end();
ite!=iteend; ++ite)
{
lcc->mark(ite, markedges); // To be sure that all darts of the basic iterator will be marked
if ( !lcc->is_marked(ite, markvertices) &&
m_drawing_functor.draw_vertex(*lcc, ite))
{
compute_vertex(ite);
CGAL::mark_cell<LCC, 0>(*lcc, ite, markvertices);
}
}
}
}
}
}
}
}
lcc.free_mark(markfaces);
lcc.free_mark(markedges);
lcc.free_mark(markvertices);
}
for (typename LCC::Dart_range::const_iterator it=lcc->darts().begin(),
itend=lcc->darts().end(); it!=itend; ++it )
{
lcc->unmark(it, markvertices);
lcc->unmark(it, markedges);
lcc->unmark(it, markfaces);
lcc->unmark(it, markvolumes);
}
lcc->free_mark(markvolumes);
lcc->free_mark(markfaces);
lcc->free_mark(markedges);
lcc->free_mark(markvertices);
}
virtual void init()
{
Base::init();
setKeyDescription(::Qt::Key_C, "Toggles random face colors");
}
virtual void keyPressEvent(QKeyEvent *e)
{
// Test key pressed:
// const ::Qt::KeyboardModifiers modifiers = e->modifiers();
// if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton)) { ... }
const ::Qt::KeyboardModifiers modifiers = e->modifiers();
if ((e->key()==::Qt::Key_C) && (modifiers==::Qt::NoButton))
{
m_random_face_color=!m_random_face_color;
displayMessage(QString("Random face color=%1.").arg(m_random_face_color?"true":"false"));
compute_elements();
redraw();
}
else
{ Base::keyPressEvent(e); } // Call the base method to process others/classicals key
// Call: * compute_elements() if the model changed, followed by
// * redraw() if some viewing parameters changed that implies some
// modifications of the buffers
// (eg. type of normal, color/mono)
// * update() just to update the drawing
// Call the base method to process others/classicals key
Base::keyPressEvent(e);
}
protected:
const LCC& lcc;
const LCC* lcc;
bool m_nofaces;
const ColorFunctor& m_fcolor;
bool m_random_face_color;
const DrawingFunctorLCC& m_drawing_functor;
};
template<class LCC, class ColorFunctor>
template<class LCC, class DrawingFunctorLCC>
void draw(const LCC& alcc,
const char* title,
bool nofill,
const ColorFunctor& fcolor)
const DrawingFunctorLCC& drawing_functor)
{
#if defined(CGAL_TEST_SUITE)
bool cgal_test_suite=true;
@ -216,11 +389,11 @@ void draw(const LCC& alcc,
int argc=1;
const char* argv[2]={"lccviewer","\0"};
QApplication app(argc,const_cast<char**>(argv));
SimpleLCCViewerQt<LCC, ColorFunctor> mainwindow(app.activeWindow(),
alcc,
title,
nofill,
fcolor);
SimpleLCCViewerQt<LCC, DrawingFunctorLCC> mainwindow(app.activeWindow(),
&alcc,
title,
nofill,
drawing_functor);
mainwindow.show();
app.exec();
}
@ -229,8 +402,8 @@ void draw(const LCC& alcc,
template<class LCC>
void draw(const LCC& alcc, const char* title, bool nofill)
{
DefaultColorFunctorLCC c;
draw(alcc, title, nofill, c);
DefaultDrawingFunctorLCC f;
draw(alcc, title, nofill, f);
}
template<class LCC>