cgal/Triangulation_3/demo/Triangulation_3/Viewer.cpp

2740 lines
105 KiB
C++

#include <boost/config.hpp>
#include <QDebug>
#if defined(BOOST_MSVC)
// Avoid warning concerning spatial_sort(QList::begin(), QList.end() QT "bug"
# pragma warning(disable: 4267 )
# pragma warning(disable: 4244 )
#endif
#include "Viewer.h"
using namespace std;
void Viewer::init()
{
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDARBPROC)this->context()->getProcAddress("glDrawArraysInstancedARB");
if(!glDrawArraysInstanced)
{
qDebug()<<"glDrawArraysInstancedARB : extension not found. Spheres will be displayed as points.";
extension_is_found = false;
}
else
extension_is_found = true;
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORARBPROC)this->context()->getProcAddress("glVertexAttribDivisorARB");
if(!glDrawArraysInstanced)
{
qDebug()<<"glVertexAttribDivisorARB : extension not found. Spheres will be displayed as points.";
extension_is_found = false;
}
else
extension_is_found = true;
// extension_is_found = false;
/* Initial timer for playing incremental construction */
m_pTimer = new QTimer(this);
connect(m_pTimer, SIGNAL(timeout()), this, SLOT(incremental_insert()));
/* Scene inits */
setBackgroundColor(::Qt::white);
// scene are defined by a sphere of 2.0, camera at the center, i.e. (0, 0, 0)
setSceneCenter( CGAL::qglviewer::Vec(-0.,-0.,-0.) );
setSceneRadius( 2. );
// show text message
setTextIsEnabled(true);
setForegroundColor(::Qt::red);
setFont(QFont("Arial Black", 16, QFont::Bold));
/* OpenGL inits */
// depth buffer setup
glClearDepthf(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
// enable semi-transparent culling planes
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// anti-aliasing, i.e. reduce jaggedness (if the OpenGL driver permits that)
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
/* Add mouse and key description */
setKeyDescription( Qt::CTRL, Qt::Key_G, tr("Generate points") );
setKeyDescription( Qt::CTRL, Qt::Key_O, tr("Load points") );
setKeyDescription( Qt::CTRL, Qt::Key_S, tr("Save points") );
setKeyDescription( Qt::CTRL, Qt::Key_Comma, tr("Preference") );
setKeyDescription( Qt::CTRL, Qt::Key_H, tr("Hide Kernel Demo") );
setKeyDescription( Qt::CTRL, Qt::Key_Q, tr("Quit Kernel Demo") );
setKeyDescription( Qt::Key_Return,
tr("Insert new point to triangulation in <u>Input-Point</u> mode") );
setKeyDescription( Qt::Key_Escape,
tr("Cancel insertion in <u>Input-Point</u> mode;<br>")
+ tr("Cancel current selection in <u>Select</u> mode") );
setKeyDescription( Qt::Key_Delete, tr("Delete selected vertices in <u>Select</u> mode") );
setMouseBindingDescription(Qt::NoModifier, Qt::LeftButton,
tr("Hold to move new point in <u>Input-Point</u> mode;<br>")
+ tr("Hold to move a vertex in <u>Move</u> mode") );
setMouseBindingDescription(Qt::ShiftModifier, Qt::LeftButton,
tr("Click to insert a vertex in <u>Input-Vertex</u> mode;<br>")
+ tr("Click to insert a point in <u>Input-Point</u> mode;<br>")
+ tr("Click or Drag to select multiple points in <u>Select</u> mode;<br>")
+ tr("Click to place a query point in <u>Find-Nearest-Neighbor</u> mode;<br>")
+ tr("Click to place a query point in <u>Show-Empty-Sphere</u> mode") );
setMouseBindingDescription(Qt::ControlModifier, Qt::LeftButton,
tr("Drag to add vertices to current selection in <u>Select</u> mode") );
compile_shaders();
are_buffers_initialized = false;
}
QString Viewer::helpString() const
{
QString text("<h1>3D Triangulation Demo</h1>");
text += "This example illustrates a generic interactive demo for 3D Triangulation in CGAL. ";
text += "This demo could be used as a simple skeleton ";
text += "for potential demos of other 3D packages or for teaching CGAL.<br><br>";
text += "The key feature is to edit vertices/points with mouse.";
text += "There are several modes:<br><br>";
text += " - <u>Normal Mode</u>: ";
text += "Rotate, zoom, or translate camera using mouse.<br>";
text += " - <u>Insert Vertex</u>: ";
text += "Insert a vertex on the surface of the trackball ";
text += "and the triangulation will be updated correspondingly.<br>";
text += " - <u>Insert Point</u>: ";
text += "Insert a point on the surface of the trackball. ";
text += "Its conflict region will be highlighted. ";
text += "When the new point is moving, ";
text += "its conflict region will be updated correspondingly.<br>";
text += " - <u>Select</u>: ";
text += "Click or drag mouse left button to select multiple points.<br>";
text += " - <u>Move</u>: Hold mouse left button to move a vertex ";
text += "and the triangulation will be updated correspondingly.<br>";
text += " - <u>Find Nearest Neighbor</u>: ";
text += "Place a query point and its nearest neighbor will be highlighted.<br>";
text += " - <u>Show Empty Sphere</u>: ";
text += "Place a query point, locate the point in a cell ";
text += "and then show the empty sphere of that cell. ";
text += "An empty sphere of a cell is a sphere ";
text += "with all four vertices of the cell lying on it ";
text += "and no other vertices inside it.<br><br>";
text += "<b>Shift+Wheel</b> to resize the trackball when it exists. ";
text += "See <b>Mouse</b> page for more details.<br><br>";
text += "Other basic features include:<br>";
text += " - Randomly generate points,<br>";
text += " - Read/Write files,<br>";
text += " - Show vertices, Voronoi edges, Delaunay edges, and/or facets,<br>";
text += " - Incremental Construct: ";
text += "Re-construct the current triangulation incrementally. ";
text += "If no triangulation exists yet, randomly generate 100 points ";
text += "and construct a Delaunay triangulation of those points.<br>";
return text;
}
/*************************************************************/
/* Shaders functions */
void Viewer::compile_shaders()
{
for(int i=0; i< vboSize; i++)
buffers[i].create();
for(int i=0; i< vaoSize; i++)
vao[i].create();
// read last setting from .ini file
readSettings();
draw_cylinder(m_fSizeDEdge,25,points_cylinder,normals_cylinder);
draw_sphere(m_fSizeVertex, 15, points_sphere, normals_sphere);
//Vertex source code
const char vertex_source[] =
{
"#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"
"}"
};
//Fragment source code
const char fragment_source[] =
{
"#version 120 \n"
"uniform highp vec4 color; \n"
"void main(void) { \n"
"gl_FragColor = color; \n"
"} \n"
"\n"
};
QOpenGLShader *vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex, this);
if(!vertex_shader->compileSourceCode(vertex_source))
{
std::cerr<<"Compiling vertex source FAILED"<<std::endl;
}
QOpenGLShader *fragment_shader= new QOpenGLShader(QOpenGLShader::Fragment, this);
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;
}
// sphere program
//Vertex source code
const char vertex_source_spheres[] =
{
"#version 120 \n"
"attribute highp vec4 vertex;\n"
"attribute highp vec3 normal;\n"
"attribute highp vec4 center;\n"
"uniform highp mat4 mvp_matrix;\n"
"uniform highp mat4 mv_matrix; \n"
"varying highp vec4 fP; \n"
"varying highp vec3 fN; \n"
"void main(void)\n"
"{\n"
" fP = mv_matrix * vertex; \n"
" fN = mat3(mv_matrix)* normal; \n"
" gl_Position = mvp_matrix * (vertex+vec4(center.xyz, 0.0)); \n"
"}"
};
//Fragment source code
const char fragment_source_spheres[] =
{
"#version 120 \n"
"varying highp vec4 fP; \n"
"varying highp vec3 fN; \n"
"uniform highp vec4 color; \n"
"uniform highp vec4 light_pos; \n"
"uniform highp vec4 light_diff; \n"
"uniform highp vec4 light_spec; \n"
"uniform highp vec4 light_amb; \n"
"uniform float spec_power ; \n"
"void main(void) { \n"
" highp vec3 L = light_pos.xyz - fP.xyz; \n"
" highp vec3 V = -fP.xyz; \n"
" highp vec3 N = normalize(fN); \n"
" L = normalize(L); \n"
" V = normalize(V); \n"
" highp vec3 R = reflect(-L, N); \n"
" highp vec4 diffuse = abs(dot(N,L)) * light_diff*color; \n"
" highp vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; \n"
"gl_FragColor = color*light_amb + diffuse + specular; \n"
"} \n"
"\n"
};
QOpenGLShader *vertex_shader_spheres = new QOpenGLShader(QOpenGLShader::Vertex, this);
if(!vertex_shader_spheres->compileSourceCode(vertex_source_spheres))
{
std::cerr<<"Compiling vertex source FAILED"<<std::endl;
}
QOpenGLShader *fragment_shader_spheres= new QOpenGLShader(QOpenGLShader::Fragment, this);
if(!fragment_shader_spheres->compileSourceCode(fragment_source_spheres))
{
std::cerr<<"Compiling fragmentsource FAILED"<<std::endl;
}
if(!rendering_program_spheres.addShader(vertex_shader_spheres))
{
std::cerr<<"adding vertex shader FAILED"<<std::endl;
}
if(!rendering_program_spheres.addShader(fragment_shader_spheres))
{
std::cerr<<"adding fragment shader FAILED"<<std::endl;
}
if(!rendering_program_spheres.link())
{
std::cerr<<"linking Program FAILED"<<std::endl;
}
// cylinder program
//Vertex source code
const char vertex_source_cylinders[] =
{
"#version 120 \n"
"attribute highp vec4 vertex;\n"
"attribute highp vec3 normal;\n"
"attribute highp vec4 transfo1;\n"
"attribute highp vec4 transfo2;\n"
"attribute highp vec4 transfo3;\n"
"attribute highp vec4 transfo4;\n"
"mat4 transfo = mat4(transfo1, transfo2, transfo3, transfo4); \n"
"uniform highp mat4 mvp_matrix;\n"
"uniform highp mat4 mv_matrix; \n"
"varying highp vec4 fP; \n"
"varying highp vec3 fN; \n"
"void main(void)\n"
"{\n"
" fP = mv_matrix * vertex; \n"
" highp vec4 TN = transfo*vec4(normal,1.0); \n"
" fN = mat3(mv_matrix)* TN.xyz; \n"
" gl_Position = mvp_matrix * transfo* vertex; \n"
"}"
};
QOpenGLShader *vertex_shader_cylinders = new QOpenGLShader(QOpenGLShader::Vertex, this);
if(!vertex_shader_cylinders->compileSourceCode(vertex_source_cylinders))
{
std::cerr<<"Compiling vertex source FAILED"<<std::endl;
}
if(!rendering_program_cylinders.addShader(vertex_shader_cylinders))
{
std::cerr<<"adding vertex shader FAILED"<<std::endl;
}
if(!rendering_program_cylinders.addShader(fragment_shader_spheres))
{
std::cerr<<"adding fragment shader FAILED"<<std::endl;
}
if(!rendering_program_cylinders.link())
{
std::cerr<<"linking Program FAILED"<<std::endl;
}
}
void Viewer::compute_elements()
{
pos_points->resize(0);
pos_delaunay->resize(0);
pos_voronoi->resize(0);
pos_facets->resize(0);
pos_newPoint->resize(0);
pos_newFacet->resize(0);
pos_selectedVertex->resize(0);
pos_movingPoint->resize(0);
pos_queryPoint->resize(0);
pos_nearest_neighbor->resize(0);
pos_emptyFacet->resize(0);
transfo1_delaunay->resize(0);
transfo2_delaunay->resize(0);
transfo3_delaunay->resize(0);
transfo4_delaunay->resize(0);
pos_trackBall->resize(0);
draw_sphere(m_fRadius, 35,points_trackBall, normals_trackBall);
for(int i=0; i<3; i++)
pos_trackBall->push_back(0.0);
pos_emptySphere->resize(0);
// Draw vertices
if ( m_pScene->m_dt.number_of_vertices()>0 ) {
for(QList<Vertex_handle>::iterator vit = m_pScene->m_vhArray.begin();
vit < m_pScene->m_vhArray.end(); ++vit) {
if( m_curMode == SELECT && (*vit)->isSeled() ) continue;
if( (*vit) == m_nearestNb ) continue;
drawVertex( (*vit)->point(), pos_points );
}//end-for-points
}//end-if-points
//Draw Delaunay Edges
for(edges_iterator eit = m_pScene->m_dt.finite_edges_begin();
eit != m_pScene->m_dt.finite_edges_end(); ++eit) {
Segment_3 seg = m_pScene->m_dt.segment(*eit);
drawEdge( seg.vertex(0), seg.vertex(1), pos_delaunay );
Vector_3 v = seg.vertex(1) - seg.vertex(0);
float length = sqrt( v.squared_length() );
// normalize
v = v / length;
// compute the angle: cos theta = v.z/1.0
GLfloat angle = acos( v.y() ) / CGAL_PI * 180;
QMatrix4x4 matrix;
matrix.setToIdentity();
// move to "from" point
matrix.translate( seg.vertex(0).x(), seg.vertex(0).y(), seg.vertex(0).z() );
// rotate from z-axis to from-->to
// axis: cross product of z-axis and from-->to
matrix.rotate( angle, v.z(), 0.0f,-v.x());
matrix.scale(1,length,1);
// stock the transformation
for(int i=0; i<4; i++)
transfo1_delaunay->push_back((float)matrix.data()[i]);
for(int i=4; i<8; i++)
transfo2_delaunay->push_back((float)matrix.data()[i]);
for(int i=8; i<12; i++)
transfo3_delaunay->push_back((float)matrix.data()[i]);
for(int i=12; i<16; i++)
transfo4_delaunay->push_back((float)matrix.data()[i]);
}//end-for-edges
// Draw Voronoi edges
for(facets_iterator fit = m_pScene->m_dt.finite_facets_begin();
fit != m_pScene->m_dt.finite_facets_end(); ++fit) {
Object_3 o = m_pScene->m_dt.dual(*fit);
if (const Segment_3 *s = CGAL::object_cast<Segment_3>(&o)) {
drawEdge( s->vertex(0), s->vertex(1), pos_voronoi );
Vector_3 v = s->vertex(1) - s->vertex(0);
float length = sqrt( v.squared_length() );
// normalize
v = v / length;
// compute the angle: cos theta = v.z/1.0
GLfloat angle = acos( v.y() ) / CGAL_PI * 180;
QMatrix4x4 matrix;
matrix.setToIdentity();
// move to "from" point
matrix.translate( s->vertex(0).x(), s->vertex(0).y(), s->vertex(0).z() );
// rotate from z-axis to from-->to
// axis: cross product of z-axis and from-->to
matrix.rotate( angle, v.z(), 0.0f,-v.x());
matrix.scale(1,length,1);
// stock the transformation
for(int i=0; i<4; i++)
transfo1_voronoi->push_back((float)matrix.data()[i]);
for(int i=4; i<8; i++)
transfo2_voronoi->push_back((float)matrix.data()[i]);
for(int i=8; i<12; i++)
transfo3_voronoi->push_back((float)matrix.data()[i]);
for(int i=12; i<16; i++)
transfo4_voronoi->push_back((float)matrix.data()[i]);
} else if (const Ray_3 *r = CGAL::object_cast<Ray_3>(&o)) {
drawEdge( r->point(0), // the source of the ray
r->point(1), // another point on the ray, different from the source
pos_voronoi );
Vector_3 v = r->point(1) - r->point(0);
float length = sqrt( v.squared_length() );
// normalize
v = v / length;
// compute the angle: cos theta = v.z/1.0
GLfloat angle = acos( v.y() ) / CGAL_PI * 180;
QMatrix4x4 matrix;
matrix.setToIdentity();
// move to "from" point
matrix.translate(r->point(0).x(), r->point(0).y(), r->point(0).z() );
// rotate from z-axis to from-->to
// axis: cross product of z-axis and from-->to
matrix.rotate( angle, v.z(), 0.0f,-v.x());
matrix.scale(1,length,1);
// stock the transformation
for(int i=0; i<4; i++)
transfo1_voronoi->push_back((float)matrix.data()[i]);
for(int i=4; i<8; i++)
transfo2_voronoi->push_back((float)matrix.data()[i]);
for(int i=8; i<12; i++)
transfo3_voronoi->push_back((float)matrix.data()[i]);
for(int i=12; i<16; i++)
transfo4_voronoi->push_back((float)matrix.data()[i]);
}
}//end-for-edges
// Draw facets
for(facets_iterator fit = m_pScene->m_dt.finite_facets_begin();
fit != m_pScene->m_dt.finite_facets_end(); ++fit) {
drawFacet( m_pScene->m_dt.triangle(*fit), pos_facets);
}//end-for-facets
// Draw the newly inserted point
drawVertex( m_newPt, pos_newPoint);
// Draw conflict region
for(QList<Facet>::iterator fit = m_boundaryFacets.begin();
fit < m_boundaryFacets.end(); ++fit) {
if( m_pScene->m_dt.is_infinite(*fit) ) continue;
drawFacet( m_pScene->m_dt.triangle(*fit), pos_newFacet); //semi-transparent purple
}//end-for-facets
// Highlight the selected vertices
for(QList<int>::iterator vit=m_vidSeled.begin(); vit<m_vidSeled.end(); ++vit) {
drawVertex( m_pScene->m_vhArray.at(*vit)->point(), pos_selectedVertex );
}//end-for-seledpts
if( m_isMoving ) {
// Highlight the moving point
drawVertex( m_pScene->m_vhArray.at( m_vidMoving )->point(), pos_movingPoint );
}//end-if-v
// Draw the nearest neighbor
if( m_nearestNb != nullptr ) {
drawVertex( m_queryPt, pos_queryPoint);
drawVertex( m_nearestNb->point(), pos_nearest_neighbor);
}
if( m_hasEmptyS ) {
// Draw the query point
drawVertex( m_queryPt, pos_queryPoint );
// Draw the cell containing that point
for(int i=0; i<4; ++i) {
if( m_pScene->m_dt.is_infinite(m_cellContain, i) ) continue;
drawFacet( m_pScene->m_dt.triangle( m_cellContain, i ), pos_emptyFacet );
}//end-for-facets
// Draw the sphere
pos_emptySphere->push_back(m_centerPt.x());
pos_emptySphere->push_back(m_centerPt.y());
pos_emptySphere->push_back(m_centerPt.z());
draw_sphere(m_fREmptyS, 35, points_emptySphere, normals_emptySphere);
}
// Draw all points during incremental mode
if( !m_incrementalPts.isEmpty() ) {
// draw the rest to-be-inserted vertices
for(QList<Point_3>::iterator pit=m_incrementalPts.begin();
pit < m_incrementalPts.end(); ++pit) {
drawVertex( (*pit), incremental_points);
}
switch( m_curStep ) {
case NEWPT:
// Highlight the next-to-insert point
drawVertex( m_curIncPt, incremental_next_point );
break;
case CELL: // show the tetrahedron that contains the point
// Highlight the next-to-insert vertex
drawVertex( m_curIncPt, incremental_next_point );
// Draw the cell containing that point
for(int i=0; i<4; ++i) {
if( m_pScene->m_dt.is_infinite(m_cellContain, i) ) continue;
drawFacet( m_pScene->m_dt.triangle( m_cellContain, i ), incremental_facet );
}//end-for-facets
break;
case CONFLICT: // show the conflict region
// Highlight the next-to-insert vertex
drawVertex( m_curIncPt, incremental_next_point );
// Draw conflict region
for(QList<Facet>::iterator fit = m_boundaryFacets.begin();
fit < m_boundaryFacets.end(); ++fit) {
if( m_pScene->m_dt.is_infinite(*fit) ) continue;
drawFacet( m_pScene->m_dt.triangle(*fit), incremental_conflict ); //semi-transparent purple
}//end-for-facets
break;
default:
break;
}//end-of=switch
}//end-if-incpts
}
void Viewer::initialize_buffers()
{
rendering_program.bind();
{
//Points
vao[0].bind();
buffers[0].bind();
buffers[0].allocate(pos_points->data(), pos_points->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[0].release();
vao[0].release();
//Delaunay Edges
vao[1].bind();
buffers[1].bind();
buffers[1].allocate(pos_delaunay->data(), pos_delaunay->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[1].release();
vao[1].release();
//Voronoi Edges
vao[2].bind();
buffers[2].bind();
buffers[2].allocate(pos_voronoi->data(), pos_voronoi->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[2].release();
vao[2].release();
//Facets
vao[3].bind();
buffers[3].bind();
buffers[3].allocate(pos_facets->data(), pos_facets->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[3].release();
vao[3].release();
//New point
vao[4].bind();
buffers[4].bind();
buffers[4].allocate(pos_newPoint->data(), pos_newPoint->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[4].release();
vao[4].release();
//New Facet
vao[5].bind();
buffers[5].bind();
buffers[5].allocate(pos_newFacet->data(), pos_newFacet->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[5].release();
vao[5].release();
//Selected Point
vao[6].bind();
buffers[6].bind();
buffers[6].allocate(pos_selectedVertex->data(), pos_selectedVertex->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[6].release();
vao[6].release();
//Moving Point
vao[7].bind();
buffers[7].bind();
buffers[7].allocate(pos_movingPoint->data(), pos_movingPoint->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[7].release();
vao[7].release();
//Query Point
vao[8].bind();
buffers[8].bind();
buffers[8].allocate(pos_queryPoint->data(), pos_queryPoint->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[8].release();
vao[8].release();
//Nearest Neighbor
vao[9].bind();
buffers[9].bind();
buffers[9].allocate(pos_nearest_neighbor->data(), pos_nearest_neighbor->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[9].release();
vao[9].release();
//Facet empty Sphere
vao[10].bind();
buffers[10].bind();
buffers[10].allocate(pos_emptyFacet->data(), pos_emptyFacet->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[10].release();
vao[10].release();
vao[21].bind();
buffers[28].bind();
buffers[28].allocate(incremental_next_point->data(), incremental_next_point->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[28].release();
vao[21].release();
vao[22].bind();
buffers[29].bind();
buffers[29].allocate(incremental_facet->data(), incremental_facet->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[29].release();
vao[22].release();
vao[23].bind();
buffers[30].bind();
buffers[30].allocate(incremental_conflict->data(), incremental_conflict->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[30].release();
vao[23].release();
vao[24].bind();
buffers[31].bind();
buffers[31].allocate(incremental_points->data(), incremental_points->size()*sizeof(float));
poly_vertexLocation[0] = rendering_program.attributeLocation("vertex");
rendering_program.enableAttributeArray(poly_vertexLocation[0]);
rendering_program.setAttributeBuffer(poly_vertexLocation[0],GL_FLOAT,0,3);
buffers[31].release();
vao[24].release();
}
rendering_program.release();
rendering_program_spheres.bind();
{
//Track Ball
vao[11].bind();
buffers[11].bind();
buffers[11].allocate(pos_trackBall->data(), pos_trackBall->size()*sizeof(float));
centerLocation[0] = rendering_program_spheres.attributeLocation("center");
rendering_program_spheres.enableAttributeArray(centerLocation[0]);
rendering_program_spheres.setAttributeBuffer(centerLocation[0],GL_FLOAT,0,3);
buffers[11].release();
buffers[12].bind();
buffers[12].allocate(normals_trackBall->data(), normals_trackBall->size()*sizeof(float));
normalsLocation[0] = rendering_program_spheres.attributeLocation("normal");
rendering_program_spheres.enableAttributeArray(normalsLocation[0]);
rendering_program_spheres.setAttributeBuffer(normalsLocation[0],GL_FLOAT,0,3);
buffers[12].release();
buffers[13].bind();
buffers[13].allocate(points_trackBall->data(), points_trackBall->size()*sizeof(float));
poly_vertexLocation[1] = rendering_program_spheres.attributeLocation("vertex");
rendering_program_spheres.enableAttributeArray(poly_vertexLocation[1]);
rendering_program_spheres.setAttributeBuffer(poly_vertexLocation[1],GL_FLOAT,0,3);
buffers[13].release();
if(extension_is_found)
{
glVertexAttribDivisor(centerLocation[0],1);
glVertexAttribDivisor(normalsLocation[0],0);
}
vao[11].release();
//Empty Sphere
vao[12].bind();
if(extension_is_found)
{
buffers[14].bind();
buffers[14].allocate(pos_emptySphere->data(), pos_emptySphere->size()*sizeof(float));
centerLocation[0] = rendering_program_spheres.attributeLocation("center");
rendering_program_spheres.enableAttributeArray(centerLocation[0]);
rendering_program_spheres.setAttributeBuffer(centerLocation[0],GL_FLOAT,0,3);
buffers[14].release();
}
buffers[32].bind();
buffers[32].allocate(normals_emptySphere->data(), normals_emptySphere->size()*sizeof(float));
normalsLocation[0] = rendering_program_spheres.attributeLocation("normal");
rendering_program_spheres.enableAttributeArray(normalsLocation[0]);
rendering_program_spheres.setAttributeBuffer(normalsLocation[0],GL_FLOAT,0,3);
buffers[32].release();
buffers[16].bind();
buffers[16].allocate(points_emptySphere->data(), points_emptySphere->size()*sizeof(float));
poly_vertexLocation[1] = rendering_program_spheres.attributeLocation("vertex");
rendering_program_spheres.enableAttributeArray(poly_vertexLocation[1]);
rendering_program_spheres.setAttributeBuffer(poly_vertexLocation[1],GL_FLOAT,0,3);
buffers[16].release();
if(extension_is_found)
{
glVertexAttribDivisor(centerLocation[0],1);
glVertexAttribDivisor(normalsLocation[0],0);
}
vao[12].release();
//Vertex Sphere
vao[13].bind();
buffers[0].bind();
centerLocation[0] = rendering_program_spheres.attributeLocation("center");
rendering_program_spheres.enableAttributeArray(centerLocation[0]);
rendering_program_spheres.setAttributeBuffer(centerLocation[0],GL_FLOAT,0,3);
buffers[0].release();
buffers[15].bind();
buffers[15].allocate(normals_sphere->data(), normals_sphere->size()*sizeof(float));
normalsLocation[0] = rendering_program_spheres.attributeLocation("normal");
rendering_program_spheres.enableAttributeArray(normalsLocation[0]);
rendering_program_spheres.setAttributeBuffer(normalsLocation[0],GL_FLOAT,0,3);
buffers[15].release();
buffers[17].bind();
buffers[17].allocate(points_sphere->data(), points_sphere->size()*sizeof(float));
poly_vertexLocation[1] = rendering_program_spheres.attributeLocation("vertex");
rendering_program_spheres.enableAttributeArray(poly_vertexLocation[1]);
rendering_program_spheres.setAttributeBuffer(poly_vertexLocation[1],GL_FLOAT,0,3);
buffers[17].release();
if(extension_is_found)
{
glVertexAttribDivisor(centerLocation[0],1);
glVertexAttribDivisor(normalsLocation[0],0);
}
vao[13].release();
//New point Sphere
vao[14].bind();
buffers[4].bind();
centerLocation[0] = rendering_program_spheres.attributeLocation("center");
rendering_program_spheres.enableAttributeArray(centerLocation[0]);
rendering_program_spheres.setAttributeBuffer(centerLocation[0],GL_FLOAT,0,3);
buffers[4].release();
buffers[15].bind();
normalsLocation[0] = rendering_program_spheres.attributeLocation("normal");
rendering_program_spheres.enableAttributeArray(normalsLocation[0]);
rendering_program_spheres.setAttributeBuffer(normalsLocation[0],GL_FLOAT,0,3);
buffers[15].release();
buffers[17].bind();
poly_vertexLocation[1] = rendering_program_spheres.attributeLocation("vertex");
rendering_program_spheres.enableAttributeArray(poly_vertexLocation[1]);
rendering_program_spheres.setAttributeBuffer(poly_vertexLocation[1],GL_FLOAT,0,3);
buffers[17].release();
if(extension_is_found)
{
glVertexAttribDivisor(centerLocation[0],1);
glVertexAttribDivisor(normalsLocation[0],0);
}
vao[14].release();
//Selected point Sphere
vao[15].bind();
buffers[6].bind();
centerLocation[0] = rendering_program_spheres.attributeLocation("center");
rendering_program_spheres.enableAttributeArray(centerLocation[0]);
rendering_program_spheres.setAttributeBuffer(centerLocation[0],GL_FLOAT,0,3);
buffers[6].release();
buffers[15].bind();
normalsLocation[0] = rendering_program_spheres.attributeLocation("normal");
rendering_program_spheres.enableAttributeArray(normalsLocation[0]);
rendering_program_spheres.setAttributeBuffer(normalsLocation[0],GL_FLOAT,0,3);
buffers[15].release();
buffers[17].bind();
poly_vertexLocation[1] = rendering_program_spheres.attributeLocation("vertex");
rendering_program_spheres.enableAttributeArray(poly_vertexLocation[1]);
rendering_program_spheres.setAttributeBuffer(poly_vertexLocation[1],GL_FLOAT,0,3);
buffers[17].release();
if(extension_is_found)
{
glVertexAttribDivisor(centerLocation[0],1);
glVertexAttribDivisor(normalsLocation[0],0);
}
vao[15].release();
//Moving point Sphere
vao[16].bind();
buffers[7].bind();
centerLocation[0] = rendering_program_spheres.attributeLocation("center");
rendering_program_spheres.enableAttributeArray(centerLocation[0]);
rendering_program_spheres.setAttributeBuffer(centerLocation[0],GL_FLOAT,0,3);
buffers[7].release();
buffers[15].bind();
normalsLocation[0] = rendering_program_spheres.attributeLocation("normal");
rendering_program_spheres.enableAttributeArray(normalsLocation[0]);
rendering_program_spheres.setAttributeBuffer(normalsLocation[0],GL_FLOAT,0,3);
buffers[15].release();
buffers[17].bind();
poly_vertexLocation[1] = rendering_program_spheres.attributeLocation("vertex");
rendering_program_spheres.enableAttributeArray(poly_vertexLocation[1]);
rendering_program_spheres.setAttributeBuffer(poly_vertexLocation[1],GL_FLOAT,0,3);
buffers[17].release();
if(extension_is_found)
{
glVertexAttribDivisor(centerLocation[0],1);
glVertexAttribDivisor(normalsLocation[0],0);
}
vao[16].release();
//Query point Sphere
vao[17].bind();
buffers[8].bind();
centerLocation[0] = rendering_program_spheres.attributeLocation("center");
rendering_program_spheres.enableAttributeArray(centerLocation[0]);
rendering_program_spheres.setAttributeBuffer(centerLocation[0],GL_FLOAT,0,3);
buffers[8].release();
buffers[15].bind();
normalsLocation[0] = rendering_program_spheres.attributeLocation("normal");
rendering_program_spheres.enableAttributeArray(normalsLocation[0]);
rendering_program_spheres.setAttributeBuffer(normalsLocation[0],GL_FLOAT,0,3);
buffers[15].release();
buffers[17].bind();
poly_vertexLocation[1] = rendering_program_spheres.attributeLocation("vertex");
rendering_program_spheres.enableAttributeArray(poly_vertexLocation[1]);
rendering_program_spheres.setAttributeBuffer(poly_vertexLocation[1],GL_FLOAT,0,3);
buffers[17].release();
if(extension_is_found)
{
glVertexAttribDivisor(centerLocation[0],1);
glVertexAttribDivisor(normalsLocation[0],0);
}
vao[17].release();
//Nearest neighbor Sphere
vao[18].bind();
buffers[9].bind();
centerLocation[0] = rendering_program_spheres.attributeLocation("center");
rendering_program_spheres.enableAttributeArray(centerLocation[0]);
rendering_program_spheres.setAttributeBuffer(centerLocation[0],GL_FLOAT,0,3);
buffers[9].release();
buffers[15].bind();
normalsLocation[0] = rendering_program_spheres.attributeLocation("normal");
rendering_program_spheres.enableAttributeArray(normalsLocation[0]);
rendering_program_spheres.setAttributeBuffer(normalsLocation[0],GL_FLOAT,0,3);
buffers[15].release();
buffers[17].bind();
poly_vertexLocation[1] = rendering_program_spheres.attributeLocation("vertex");
rendering_program_spheres.enableAttributeArray(poly_vertexLocation[1]);
rendering_program_spheres.setAttributeBuffer(poly_vertexLocation[1],GL_FLOAT,0,3);
buffers[17].release();
if(extension_is_found)
{
glVertexAttribDivisor(centerLocation[0],1);
glVertexAttribDivisor(normalsLocation[0],0);
}
vao[18].release();
//incremental list
vao[25].bind();
buffers[31].bind();
rendering_program_spheres.enableAttributeArray(centerLocation[0]);
rendering_program_spheres.setAttributeBuffer(centerLocation[0],GL_FLOAT,0,3);
buffers[31].release();
buffers[15].bind();
normalsLocation[0] = rendering_program_spheres.attributeLocation("normal");
rendering_program_spheres.enableAttributeArray(normalsLocation[0]);
rendering_program_spheres.setAttributeBuffer(normalsLocation[0],GL_FLOAT,0,3);
buffers[15].release();
buffers[17].bind();
poly_vertexLocation[1] = rendering_program_spheres.attributeLocation("vertex");
rendering_program_spheres.enableAttributeArray(poly_vertexLocation[1]);
rendering_program_spheres.setAttributeBuffer(poly_vertexLocation[1],GL_FLOAT,0,3);
buffers[17].release();
if(extension_is_found)
{
glVertexAttribDivisor(centerLocation[0],1);
glVertexAttribDivisor(normalsLocation[0],0);
}
vao[25].release();
//incremental next point
vao[26].bind();
buffers[28].bind();
rendering_program_spheres.enableAttributeArray(centerLocation[0]);
rendering_program_spheres.setAttributeBuffer(centerLocation[0],GL_FLOAT,0,3);
buffers[28].release();
buffers[15].bind();
normalsLocation[0] = rendering_program_spheres.attributeLocation("normal");
rendering_program_spheres.enableAttributeArray(normalsLocation[0]);
rendering_program_spheres.setAttributeBuffer(normalsLocation[0],GL_FLOAT,0,3);
buffers[15].release();
buffers[17].bind();
poly_vertexLocation[1] = rendering_program_spheres.attributeLocation("vertex");
rendering_program_spheres.enableAttributeArray(poly_vertexLocation[1]);
rendering_program_spheres.setAttributeBuffer(poly_vertexLocation[1],GL_FLOAT,0,3);
buffers[17].release();
if(extension_is_found)
{
glVertexAttribDivisor(centerLocation[0],1);
glVertexAttribDivisor(normalsLocation[0],0);
}
vao[26].release();
}
rendering_program_spheres.release();
rendering_program_cylinders.bind();
{
vao[19].bind();
buffers[18].bind();
buffers[18].allocate(points_cylinder->data(), points_cylinder->size()*sizeof(float));
poly_vertexLocation[2] = rendering_program_cylinders.attributeLocation("vertex");
rendering_program_cylinders.enableAttributeArray(poly_vertexLocation[2]);
rendering_program_cylinders.setAttributeBuffer(poly_vertexLocation[2],GL_FLOAT,0,3);
buffers[18].release();
buffers[19].bind();
buffers[19].allocate(normals_cylinder->data(), normals_cylinder->size()*sizeof(float));
normalsLocation[1] = rendering_program_cylinders.attributeLocation("normal");
rendering_program_cylinders.enableAttributeArray(normalsLocation[1]);
rendering_program_cylinders.setAttributeBuffer(normalsLocation[1],GL_FLOAT,0,3);
buffers[19].release();
buffers[20].bind();
buffers[20].allocate(transfo1_delaunay->data(), transfo1_delaunay->size()*sizeof(float));
centerLocation[1] = rendering_program_cylinders.attributeLocation("transfo1");
rendering_program_cylinders.enableAttributeArray(centerLocation[1]);
rendering_program_cylinders.setAttributeBuffer(centerLocation[1],GL_FLOAT,0,4);
buffers[20].release();
buffers[21].bind();
buffers[21].allocate(transfo2_delaunay->data(), transfo2_delaunay->size()*sizeof(float));
centerLocation[2] = rendering_program_cylinders.attributeLocation("transfo2");
rendering_program_cylinders.enableAttributeArray(centerLocation[2]);
rendering_program_cylinders.setAttributeBuffer(centerLocation[2],GL_FLOAT,0,4);
buffers[21].release();
buffers[22].bind();
buffers[22].allocate(transfo3_delaunay->data(), transfo3_delaunay->size()*sizeof(float));
centerLocation[3] = rendering_program_cylinders.attributeLocation("transfo3");
rendering_program_cylinders.enableAttributeArray(centerLocation[3]);
rendering_program_cylinders.setAttributeBuffer(centerLocation[3],GL_FLOAT,0,4);
buffers[22].release();
buffers[23].bind();
buffers[23].allocate(transfo4_delaunay->data(), transfo4_delaunay->size()*sizeof(float));
centerLocation[4] = rendering_program_cylinders.attributeLocation("transfo4");
rendering_program_cylinders.enableAttributeArray(centerLocation[4]);
rendering_program_cylinders.setAttributeBuffer(centerLocation[4],GL_FLOAT,0,4);
buffers[23].release();
if(extension_is_found)
{
glVertexAttribDivisor(centerLocation[1],1);
glVertexAttribDivisor(centerLocation[2],1);
glVertexAttribDivisor(centerLocation[3],1);
glVertexAttribDivisor(centerLocation[4],1);
glVertexAttribDivisor(normalsLocation[1],0);
}
vao[19].release();
vao[20].bind();
buffers[18].bind();
poly_vertexLocation[2] = rendering_program_cylinders.attributeLocation("vertex");
rendering_program_cylinders.enableAttributeArray(poly_vertexLocation[2]);
rendering_program_cylinders.setAttributeBuffer(poly_vertexLocation[2],GL_FLOAT,0,3);
buffers[18].release();
buffers[19].bind();
normalsLocation[1] = rendering_program_cylinders.attributeLocation("normal");
rendering_program_cylinders.enableAttributeArray(normalsLocation[1]);
rendering_program_cylinders.setAttributeBuffer(normalsLocation[1],GL_FLOAT,0,3);
buffers[19].release();
buffers[24].bind();
buffers[24].allocate(transfo1_voronoi->data(), transfo1_voronoi->size()*sizeof(float));
centerLocation[1] = rendering_program_cylinders.attributeLocation("transfo1");
rendering_program_cylinders.enableAttributeArray(centerLocation[1]);
rendering_program_cylinders.setAttributeBuffer(centerLocation[1],GL_FLOAT,0,4);
buffers[24].release();
buffers[25].bind();
buffers[25].allocate(transfo2_voronoi->data(), transfo2_voronoi->size()*sizeof(float));
centerLocation[2] = rendering_program_cylinders.attributeLocation("transfo2");
rendering_program_cylinders.enableAttributeArray(centerLocation[2]);
rendering_program_cylinders.setAttributeBuffer(centerLocation[2],GL_FLOAT,0,4);
buffers[25].release();
buffers[26].bind();
buffers[26].allocate(transfo3_voronoi->data(), transfo3_voronoi->size()*sizeof(float));
centerLocation[3] = rendering_program_cylinders.attributeLocation("transfo3");
rendering_program_cylinders.enableAttributeArray(centerLocation[3]);
rendering_program_cylinders.setAttributeBuffer(centerLocation[3],GL_FLOAT,0,4);
buffers[26].release();
buffers[27].bind();
buffers[27].allocate(transfo4_voronoi->data(), transfo4_voronoi->size()*sizeof(float));
centerLocation[4] = rendering_program_cylinders.attributeLocation("transfo4");
rendering_program_cylinders.enableAttributeArray(centerLocation[4]);
rendering_program_cylinders.setAttributeBuffer(centerLocation[4],GL_FLOAT,0,4);
buffers[27].release();
if(extension_is_found)
{
glVertexAttribDivisor(centerLocation[1],1);
glVertexAttribDivisor(centerLocation[2],1);
glVertexAttribDivisor(centerLocation[3],1);
glVertexAttribDivisor(centerLocation[4],1);
glVertexAttribDivisor(normalsLocation[1],0);
}
vao[20].release();
}
rendering_program_cylinders.release();
are_buffers_initialized = true;
}
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];
}
QVector4D position(0.0f,0.0f,1.0f,1.0f );
// Ambient
ambient[0] = 0.29225f;
ambient[1] = 0.29225f;
ambient[2] = 0.29225f;
ambient[3] = 1.0f;
// Diffuse
diffuse[0] = 0.50754f;
diffuse[1] = 0.50754f;
diffuse[2] = 0.50754f;
diffuse[3] = 1.0f;
// Specular
specular[0] = 0.508273f;
specular[1] = 0.508273f;
specular[2] = 0.508273f;
specular[3] = 1.0f;
// Shininess
shininess = 51.2f;
rendering_program.bind();
mvpLocation[0] = rendering_program.uniformLocation("mvp_matrix");
colorLocation[0] = rendering_program.uniformLocation("color");
rendering_program.setUniformValue(mvpLocation[0], mvpMatrix);
rendering_program.release();
rendering_program_spheres.bind();
colorLocation[1] = rendering_program_spheres.uniformLocation("color");
mvpLocation[1] = rendering_program_spheres.uniformLocation("mvp_matrix");
mvLocation[0] = rendering_program_spheres.uniformLocation("mv_matrix");
lightLocation[0] = rendering_program_spheres.uniformLocation("light_pos");
lightLocation[1] = rendering_program_spheres.uniformLocation("light_diff");
lightLocation[2] = rendering_program_spheres.uniformLocation("light_spec");
lightLocation[3] = rendering_program_spheres.uniformLocation("light_amb");
lightLocation[4] = rendering_program_spheres.uniformLocation("spec_power");
rendering_program_spheres.setUniformValue(lightLocation[0], position);
rendering_program_spheres.setUniformValue(mvpLocation[1], mvpMatrix);
rendering_program_spheres.setUniformValue(mvLocation[0], mvMatrix);
rendering_program_spheres.setUniformValue(lightLocation[1], diffuse);
rendering_program_spheres.setUniformValue(lightLocation[2], specular);
rendering_program_spheres.setUniformValue(lightLocation[3], ambient);
rendering_program_spheres.setUniformValue(lightLocation[4], shininess);
rendering_program_spheres.release();
rendering_program_cylinders.bind();
colorLocation[2] = rendering_program_cylinders.uniformLocation("color");
mvpLocation[2] = rendering_program_cylinders.uniformLocation("mvp_matrix");
mvLocation[1] = rendering_program_cylinders.uniformLocation("mv_matrix");
lightLocation[5] = rendering_program_cylinders.uniformLocation("light_pos");
lightLocation[6] = rendering_program_cylinders.uniformLocation("light_diff");
lightLocation[7] = rendering_program_cylinders.uniformLocation("light_spec");
lightLocation[8] = rendering_program_cylinders.uniformLocation("light_amb");
lightLocation[9] = rendering_program_cylinders.uniformLocation("spec_power");
rendering_program_cylinders.setUniformValue(lightLocation[5], position);
rendering_program_cylinders.setUniformValue(lightLocation[6], diffuse);
rendering_program_cylinders.setUniformValue(lightLocation[7], specular);
rendering_program_cylinders.setUniformValue(lightLocation[8], ambient);
rendering_program_cylinders.setUniformValue(lightLocation[9], shininess);
rendering_program_cylinders.setUniformValue(mvpLocation[2], mvpMatrix);
rendering_program_cylinders.setUniformValue(mvLocation[1], mvMatrix);
rendering_program_cylinders.release();
}
/*************************************************************/
/* Draw functions */
void Viewer::draw()
{
glEnable(GL_DEPTH_TEST);
if(!are_buffers_initialized)
initialize_buffers();
QFont fontPrompt("Arial", 8);
attrib_buffers(this);
if(m_isFlat || !extension_is_found)
{
if(m_showVertex)
{
rendering_program.bind();
vao[0].bind();
rendering_program.setUniformValue(colorLocation[0], m_colorVertex);
rendering_program.setUniformValue("point_size", 8.0f);
glDrawArrays(GL_POINTS, 0, pos_points->size()/3);
vao[0].release();
rendering_program.release();
}
if(m_showDEdge)
{
rendering_program.bind();
vao[1].bind();
rendering_program.setUniformValue(colorLocation[0], m_colorDEdge);
glDrawArrays(GL_LINES, 0, pos_delaunay->size()/3);
vao[1].release();
rendering_program.release();
}
if(m_showVEdge)
{
rendering_program.bind();
vao[2].bind();
rendering_program.setUniformValue(colorLocation[0], m_colorVEdge);
glDrawArrays(GL_LINES, 0, pos_voronoi->size()/3);
vao[2].release();
rendering_program.release();
}
// Insert point mode
if( m_curMode == INSERT_PT) {
// Show prompt messages
drawText( width()-200, 20, tr("Shift+Left: Insert a point"), fontPrompt );
drawText( width()-200, 40, tr("Hold Left: Move the point"), fontPrompt );
drawText( width()-200, 60, tr("Return: Insert to DT"), fontPrompt );
drawText( width()-200, 80, tr("Escape: Cancel insertion"), fontPrompt );
drawText( width()-200, 100, tr("Shift+Wheel: Resize trackball"), fontPrompt );
if( m_hasNewPt ) {
rendering_program.bind();
vao[4].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program.setUniformValue(colorLocation[0], color);
glDrawArrays(GL_POINTS, 0, pos_newPoint->size()/3);
vao[4].release();
vao[5].bind();
color.setRgb(215, 80, 0, 96);
rendering_program.setUniformValue(colorLocation[0], color);
glDrawArrays(GL_TRIANGLES, 0, pos_newFacet->size()/3);
vao[5].release();
rendering_program.release();
}
}
else if( m_curMode == SELECT) {
// Show prompt messages
drawText( width()-200, 20, tr("Shift+Left: Select"), fontPrompt );
drawText( width()-200, 40, tr("Ctrl+Left: Add selection"),
QFont("Arial", 14) );
drawText( width()-200, 60, tr("Escape: Cancel selection"), fontPrompt );
drawText( width()-200, 80, tr("DEL: Delete selected"), fontPrompt );
rendering_program.bind();
vao[6].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program.setUniformValue(colorLocation[0], color);
glDrawArrays(GL_POINTS, 0, pos_selectedVertex->size()/3);
vao[6].release();
rendering_program.release();
}
else if( m_curMode == MOVE ) {
// Show prompt messages
drawText( width()-200, 20, tr("Left Click: Select"), fontPrompt );
if(m_isMoving)
drawText( width()-200, 40, tr("Shift+Wheel: Resize trackball"), fontPrompt );
rendering_program.bind();
vao[7].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program.setUniformValue(colorLocation[0], color);
glDrawArrays(GL_POINTS, 0, pos_movingPoint->size()/3);
vao[7].release();
rendering_program.release();
}
else if( m_curMode == FINDNB ) {
// Show prompt messages
drawText( width()-200, 20, tr("Shift+Left: Place query point"), fontPrompt );
drawText( width()-200, 40, tr("Shift+Wheel: Resize trackball"), fontPrompt );
rendering_program.bind();
vao[8].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program.setUniformValue(colorLocation[0], color);
glDrawArrays(GL_POINTS, 0, pos_queryPoint->size()/3);
vao[8].release();
vao[9].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program.setUniformValue(colorLocation[0], color);
glDrawArrays(GL_POINTS, 0, pos_nearest_neighbor->size()/3);
vao[9].release();
rendering_program.release();
}
else if(m_curMode == EMPTYSPH){
// Show prompt messages
drawText( width()-200, 20, tr("Shift+Left: Place query point"), fontPrompt );
drawText( width()-200, 40, tr("Press S: Show/Hide trackball"), fontPrompt );
drawText( width()-200, 60, tr("Shift+Wheel: Resize trackball"), fontPrompt );
rendering_program.bind();
vao[8].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program.setUniformValue(colorLocation[0], color);
glDrawArrays(GL_POINTS, 0, pos_queryPoint->size()/3);
vao[8].release();
vao[10].bind();
rendering_program.setUniformValue(colorLocation[0], m_colorFacet);
glDrawArrays(GL_TRIANGLES, 0, pos_emptyFacet->size()/3);
vao[10].release();
rendering_program.release();
}
// Draw all points during incremental mode
if( !m_incrementalPts.isEmpty() ) {
// draw the rest to-be-inserted vertices
rendering_program.bind();
vao[24].bind();
color.setRgbF(0.7f,0.7f,0.7f);
rendering_program.setUniformValue(colorLocation[0],color);
rendering_program.setUniformValue("point_size", 8.0f);
glDrawArrays(GL_POINTS, 0, incremental_points->size()/3);
vao[24].release();
rendering_program.release();
switch( m_curStep ) {
case NEWPT:
// Show prompt messages
drawText( 10, 20, tr("Highlight the next-to-insert point"), fontPrompt );
// Highlight the next-to-insert point
rendering_program.bind();
vao[21].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program.setUniformValue(colorLocation[0], color);
rendering_program.setUniformValue("point_size", 8.0f);
glDrawArrays(GL_POINTS, 0, incremental_next_point->size()/3);
vao[21].release();
rendering_program.release();
break;
case CELL: // show the tetrahedron that contains the point
// Show prompt messages
drawText( 10, 20, tr("Show the tetrahedron containing the point"), fontPrompt );
drawText( 10, 40, tr("(Only finite facets are drawn)"), fontPrompt );
// Highlight the next-to-insert vertex
rendering_program.bind();
vao[21].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program.setUniformValue(colorLocation[0], color);
rendering_program.setUniformValue("point_size", 8.0f);
glDrawArrays(GL_POINTS, 0, incremental_next_point->size()/3);
vao[21].release();
rendering_program.release();
// Draw the cell containing that point
rendering_program.bind();
vao[22].bind();
rendering_program.setUniformValue(colorLocation[0], m_colorFacet);
glDrawArrays(GL_TRIANGLES, 0, incremental_facet->size()/3);
vao[22].release();
rendering_program.release();
break;
case CONFLICT: // show the conflict region
// Show prompt messages
drawText( 10, 20, tr("Show the conflict region"), fontPrompt );
// Highlight the next-to-insert vertex
rendering_program.bind();
vao[21].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program.setUniformValue(colorLocation[0], color);
rendering_program.setUniformValue("point_size", 8.0f);
glDrawArrays(GL_POINTS, 0, incremental_next_point->size()/3);
vao[21].release();
rendering_program.release();
// Draw conflict region
rendering_program.bind();
vao[23].bind();
color.setRgb(215, 80, 0, 96);
rendering_program.setUniformValue(colorLocation[0], color);
glDrawArrays(GL_TRIANGLES, 0, incremental_facet->size()/3);
vao[23].release();
rendering_program.release();
break;
default:
break;
}//end-of=switch
}//end-if-incpts
}
else
{
if(m_showVertex)
{
rendering_program_spheres.bind();
vao[13].bind();
rendering_program_spheres.setUniformValue(colorLocation[1], m_colorVertex);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_sphere->size()/3, pos_points->size()/3);
vao[13].release();
rendering_program.release();
}
if(m_showDEdge)
{
rendering_program_cylinders.bind();
vao[19].bind();
rendering_program_cylinders.setUniformValue(colorLocation[2], m_colorDEdge);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_cylinder->size()/3, transfo1_delaunay->size()/4);
vao[19].release();
rendering_program_cylinders.release();
}
if(m_showVEdge)
{
rendering_program_cylinders.bind();
vao[20].bind();
rendering_program_cylinders.setUniformValue(colorLocation[2], m_colorVEdge);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_cylinder->size()/3, transfo1_voronoi->size()/4);
vao[20].release();
rendering_program_cylinders.release();
}
if( m_curMode == INSERT_PT) {
// Show prompt messages
drawText( width()-200, 20, tr("Shift+Left: Insert a point"), fontPrompt );
drawText( width()-200, 40, tr("Hold Left: Move the point"), fontPrompt );
drawText( width()-200, 60, tr("Return: Insert to DT"), fontPrompt );
drawText( width()-200, 80, tr("Escape: Cancel insertion"), fontPrompt );
drawText( width()-200, 100, tr("Shift+Wheel: Resize trackball"), fontPrompt );
if( m_hasNewPt ) {
rendering_program_spheres.bind();
vao[14].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program_spheres.setUniformValue(colorLocation[1], color);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_sphere->size()/3, pos_newPoint->size()/3);
vao[14].release();
rendering_program_spheres.release();
rendering_program.bind();
vao[5].bind();
color.setRgb(215, 80, 0, 96);
rendering_program.setUniformValue(colorLocation[0], color);
glDrawArrays(GL_TRIANGLES, 0, pos_newFacet->size()/3);
vao[5].release();
rendering_program.release();
}
}
else if( m_curMode == SELECT) {
// Show prompt messages
drawText( width()-200, 20, tr("Shift+Left: Select"), fontPrompt );
drawText( width()-200, 40, tr("Ctrl+Left: Add selection"),
QFont("Arial", 14) );
drawText( width()-200, 60, tr("Escape: Cancel selection"), fontPrompt );
drawText( width()-200, 80, tr("DEL: Delete selected"), fontPrompt );
rendering_program_spheres.bind();
vao[15].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program_spheres.setUniformValue(colorLocation[1], color);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_sphere->size()/3, pos_selectedVertex->size()/3);
vao[15].release();
rendering_program_spheres.release();
}
else if( m_curMode == MOVE ) {
// Show prompt messages
drawText( width()-200, 20, tr("Left Click: Select"), fontPrompt );
if(m_isMoving)
drawText( width()-200, 40, tr("Shift+Wheel: Resize trackball"), fontPrompt );
rendering_program_spheres.bind();
vao[16].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program_spheres.setUniformValue(colorLocation[1], color);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_sphere->size()/3, pos_movingPoint->size()/3);
vao[16].release();
rendering_program_spheres.release();
}
else if( m_curMode == FINDNB ) {
// Show prompt messages
drawText( width()-200, 20, tr("Shift+Left: Place query point"), fontPrompt );
drawText( width()-200, 40, tr("Shift+Wheel: Resize trackball"), fontPrompt );
rendering_program_spheres.bind();
vao[17].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program_spheres.setUniformValue(colorLocation[1], color);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_sphere->size()/3, pos_queryPoint->size()/3);
vao[17].release();
rendering_program_spheres.release();
rendering_program_spheres.bind();
vao[18].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program_spheres.setUniformValue(colorLocation[1], color);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_sphere->size()/3, pos_nearest_neighbor->size()/3);
vao[18].release();
rendering_program_spheres.release();
}
else if(m_curMode == EMPTYSPH){
// Show prompt messages
drawText( width()-200, 20, tr("Shift+Left: Place query point"), fontPrompt );
drawText( width()-200, 40, tr("Press S: Show/Hide trackball"), fontPrompt );
drawText( width()-200, 60, tr("Shift+Wheel: Resize trackball"), fontPrompt );
rendering_program_spheres.bind();
vao[17].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program_spheres.setUniformValue(colorLocation[1], color);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_sphere->size()/3, pos_queryPoint->size()/3);
vao[17].release();
rendering_program_spheres.release();
rendering_program.bind();
vao[10].bind();
rendering_program.setUniformValue(colorLocation[0], m_colorFacet);
glDrawArrays(GL_TRIANGLES, 0, pos_emptyFacet->size()/3);
vao[10].release();
rendering_program.release();
}
// Draw all points during incremental mode
if( !m_incrementalPts.isEmpty() ) {
// draw the rest to-be-inserted vertices
rendering_program_spheres.bind();
vao[25].bind();
color.setRgbF(0.7f,0.7f,0.7f);
rendering_program_spheres.setUniformValue(colorLocation[1],color);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_sphere->size()/3, incremental_points->size()/3);
vao[25].release();
rendering_program_spheres.release();
switch( m_curStep ) {
case NEWPT:
// Show prompt messages
drawText( 10, 20, tr("Highlight the next-to-insert point"), fontPrompt );
// Highlight the next-to-insert point
rendering_program_spheres.bind();
vao[26].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program_spheres.setUniformValue(colorLocation[1],color);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_sphere->size()/3, incremental_next_point->size()/3);
vao[26].release();
rendering_program_spheres.release();
break;
case CELL: // show the tetrahedron that contains the point
// Show prompt messages
drawText( 10, 20, tr("Show the tetrahedron containing the point"), fontPrompt );
drawText( 10, 40, tr("(Only finite facets are drawn)"), fontPrompt );
// Highlight the next-to-insert vertex
rendering_program_spheres.bind();
vao[26].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program_spheres.setUniformValue(colorLocation[1], color);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_sphere->size()/3, incremental_next_point->size()/3);
vao[26].release();
rendering_program_spheres.release();
// Draw the cell containing that point
rendering_program.bind();
vao[22].bind();
rendering_program.setUniformValue(colorLocation[0], m_colorFacet);
glDrawArrays(GL_TRIANGLES, 0, incremental_facet->size()/3);
vao[22].release();
rendering_program.release();
break;
case CONFLICT: // show the conflict region
// Show prompt messages
drawText( 10, 20, tr("Show the conflict region"), fontPrompt );
// Highlight the next-to-insert vertex
rendering_program_spheres.bind();
vao[26].bind();
color.setRgbF(1.0,0.0,0.0);
rendering_program_spheres.setUniformValue(colorLocation[1], color);
glDrawArraysInstanced(GL_TRIANGLES, 0, points_sphere->size()/3, incremental_next_point->size()/3);
vao[26].release();
rendering_program_spheres.release();
// Draw conflict region
rendering_program.bind();
vao[23].bind();
color.setRgb(215, 80, 0, 96);
rendering_program.setUniformValue(colorLocation[0], color);
glDrawArrays(GL_TRIANGLES, 0, incremental_facet->size()/3);
vao[23].release();
rendering_program.release();
break;
default:
break;
}//end-of=switch
}//end-if-incpts
}
if(m_showFacet)
{
rendering_program.bind();
vao[3].bind();
rendering_program.setUniformValue(colorLocation[0], m_colorFacet);
glDrawArrays(GL_TRIANGLES, 0, pos_facets->size()/3);
vao[3].release();
rendering_program.release();
}
if( m_curMode == INSERT_V ) {
// Show prompt messages
drawText( width()-200, 20, tr("Shift+Left: Insert a vertex"), fontPrompt );
drawText( width()-200, 40, tr("Shift+Wheel: Resize trackball"), fontPrompt );
}
if(m_curMode != NONE && m_curMode != SELECT && m_showTrackball)
{
rendering_program_spheres.bind();
vao[11].bind();
rendering_program_spheres.setUniformValue(colorLocation[1], m_colorTrackball);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if(extension_is_found)
glDrawArraysInstanced(GL_TRIANGLES, 0, points_trackBall->size()/3, 1);
else
glDrawArrays(GL_TRIANGLES, 0, points_trackBall->size()/3);
glDisable(GL_BLEND);
vao[11].release();
rendering_program_spheres.release();
}
if(m_curMode ==EMPTYSPH)
{
rendering_program_spheres.bind();
vao[12].bind();
rendering_program_spheres.setUniformValue(colorLocation[1], m_colorEmptySphere);
if(extension_is_found)
glDrawArraysInstanced(GL_TRIANGLES, 0, points_emptySphere->size()/3, pos_emptySphere->size()/3);
else if(pos_emptySphere->size()>0)
{
rendering_program_spheres.setAttributeValue("center", QVector4D(pos_emptySphere->at(0), pos_emptySphere->at(1), pos_emptySphere->at(2), 1.0));
glDrawArrays(GL_TRIANGLES, 0, points_emptySphere->size()/3);
}
vao[12].release();
rendering_program_spheres.release();
}
}
void Viewer::drawVertex(const Point_3& p, Coords_ptr& vertices)
{
vertices->push_back(p.x()); vertices->push_back(p.y()); vertices->push_back(p.z());
}
void Viewer::drawEdge(const Point_3& from, const Point_3& to, Coords_ptr& vertices)
{
vertices->push_back( from.x()); vertices->push_back(from.y()); vertices->push_back(from.z());
vertices->push_back( to.x()); vertices->push_back(to.y()); vertices->push_back(to.z());
}
void Viewer::drawFacet(const Triangle_3& t, Coords_ptr& vertices)
{
Point_3 p0 = t.vertex(0);
Point_3 p1 = t.vertex(1);
Point_3 p2 = t.vertex(2);
vertices->push_back( p0.x()); vertices->push_back(p0.y()); vertices->push_back(p0.z());
vertices->push_back( p1.x()); vertices->push_back(p1.y()); vertices->push_back(p1.z());
vertices->push_back( p2.x()); vertices->push_back(p2.y()); vertices->push_back(p2.z());
}
/*************************************************************/
/* Select functions */
void Viewer::drawWithNames()
{
makeCurrent();
glEnable(GL_DEPTH_TEST);
for(int i=0; i<m_pScene->m_vhArray.size(); ++i) {
//clear depth
glClearDepthf(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//draw point
Point_3& p = m_pScene->m_vhArray.at(i)->point();
GLfloat buf[3];
buf[0]=p.x();
buf[1]=p.y();
buf[2]=p.z();
rendering_program.bind();
vao[27].bind();
buffers[33].bind();
buffers[33].allocate(buf, 3*sizeof(GLfloat));
rendering_program.enableAttributeArray("vertex");
rendering_program.setAttributeArray("vertex",GL_FLOAT,nullptr,3);
buffers[33].release();
vao[3].release();
QMatrix4x4 mvpMatrix;
double mat[16];
camera()->getModelViewProjectionMatrix(mat);
for(int j=0; j < 16; j++)
{
mvpMatrix.data()[j] = (float)mat[j];
}
rendering_program.bind();
vao[27].bind();
rendering_program.setUniformValue("mvp_matrix", mvpMatrix);
rendering_program.setUniformValue("point_size", 8.0f);
glDrawArrays(GL_POINTS,0,1);
vao[27].release();
rendering_program.release();
//read depth and store in map
GLfloat depth = 2.0f;
depth = read_depth_under_pixel(picking_pos, this, this->camera());
if (depth < 2.0f)
{
picked_IDs[depth] = i;
}
}//end-for-points
// push a name for the newly inserted point
if( m_curMode == INSERT_PT && m_hasNewPt ) {
//clear depth
glClearDepthf(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//draw point
GLfloat buf[3];
buf[0]=m_newPt.x();
buf[1]=m_newPt.y();
buf[2]=m_newPt.z();
rendering_program.bind();
vao[27].bind();
buffers[33].bind();
buffers[33].allocate(buf, 3*sizeof(GLfloat));
rendering_program.enableAttributeArray("vertex");
rendering_program.setAttributeArray("vertex",GL_FLOAT,nullptr,3);
buffers[33].release();
QMatrix4x4 mvpMatrix;
double mat[16];
camera()->getModelViewProjectionMatrix(mat);
for(int i=0; i < 16; i++)
{
mvpMatrix.data()[i] = (float)mat[i];
}
rendering_program.bind();
rendering_program.setUniformValue("mvp_matrix", mvpMatrix);
rendering_program.setUniformValue("point_size", 16.0f);
rendering_program.setUniformValue("color", m_colorVertex);
glDrawArrays(GL_POINTS,0,1);
vao[3].release();
rendering_program.release();
//read depth and store in map
GLfloat depth = 2.0f;
depth = read_depth_under_pixel(picking_pos, this, this->camera());
if (depth < 2.0f)
{
picked_IDs[depth] = -1;
}
}//end-if-newPt
}
void Viewer::beginSelection(const QPoint &point)
{
picking_pos = point;
CGAL::QGLViewer::beginSelection(point);
}
void Viewer::endSelection(const QPoint& p)
{
CGAL::QGLViewer::endSelection(p);
// flush GL buffers
glFlush();
bool picked = false;
int id = 0;
QList<float> depths = picked_IDs.keys();
if(!depths.isEmpty())
{
std::sort(depths.begin(), depths.end());
id = picked_IDs[depths.first()];
picked = true;
}
/* No selection */
if( !picked) {
if( m_curMode == SELECT )
m_isPress = false;
}//end-if-notselected
/* Check whether the new point is clicked on */
else if( m_curMode == INSERT_PT ) {
if( m_hasNewPt && (id == -1 ))
m_isMoving = true;
}//end-if-inspt
/* Check whether vertex is clicked on */
else if( m_curMode == MOVE ) {
m_isMoving = true;
m_vidMoving = id;
// compute the corresponding size of trackball, i.e. selectedV is on the ball
Point_3 p = m_pScene->m_vhArray.at( m_vidMoving )->point();
m_fRadius = sqrt( p.x()*p.x() + p.y()*p.y() + p.z()*p.z() );
}//end-if-move
/* Store current selections */
else { // m_curMode == SELECT
if( m_selMode == NORMAL ) {
// remove the old selections
for(QList<int>::iterator vit=m_vidSeled.begin();
vit < m_vidSeled.end(); ++vit) {
m_pScene->m_vhArray.at(*vit)->setSeled( false );
}
m_vidSeled.clear();
// record the new selections
m_vidSeled.push_back(id);
m_pScene->m_vhArray.at( m_vidSeled.back() )->setSeled();
} else {
if( !m_vidSeled.contains(id)) {
m_vidSeled.push_back( id );
m_pScene->m_vhArray.at( id )->setSeled();
}//end-if-contain
}//end-if-add
}//end-if-sel
changed();
}
/*************************************************************/
/* Mouse and Keyboard functions */
void Viewer::mousePressEvent(QMouseEvent *event)
{
// button() holds the button that caused the event
// note: for mouse move event, button() always return Qt::NoButton
// modifiers() holds the keyboard modifier flags at the time of the event
// buttons() holds the button state when the event was generated,
// i.e. all buttons that are pressed down
// pos() holds the mouse cursor's position relative to the receiving widget
// Get event modifiers key
const Qt::KeyboardModifiers modifiers = event->modifiers();
if( m_curMode == INSERT_V
&& event->button() == Qt::LeftButton && modifiers == Qt::SHIFT ) {
m_isPress = true;
}//end-if-insv
else if(m_curMode == INSERT_PT && event->button() == Qt::LeftButton ) {
/* shift+left to insert */
if( modifiers == Qt::SHIFT ) {
if( m_pScene->m_dt.is_valid() && m_pScene->m_dt.dimension() == 3 )
m_isPress = true;
else
displayMessage( tr("There exists no triangulation yet.") );
m_hasNewPt = false;
} else { /* left button to move */
m_isMoving = false;
// define selection window (default was 3)
setSelectRegionWidth( 10 );
setSelectRegionHeight( 10 );
// perform the selection
select( event->pos() );
if( m_isMoving )
// redraw window
{ changed();
update();
}
else
// if no point is selected, then regular action (rotation) will be performed
CGAL::QGLViewer::mousePressEvent(event);
}//end-if-shift
}//end-if-inspt
else if( m_curMode == SELECT && event->button() == Qt::LeftButton ) {
// set the selection mode
switch( modifiers ) {
case Qt::SHIFT : // select
m_isPress = true;
m_selMode = NORMAL;
// initialize multiple selection window
m_rectSel = QRect( event->pos(), event->pos() );
// redraw window
update();
break;
case Qt::CTRL : // add selection
m_isPress = true;
m_selMode = ADD;
// initialize multiple selection window
m_rectSel = QRect( event->pos(), event->pos() );
// redraw window
update();
break;
default: // rotate
CGAL::QGLViewer::mousePressEvent(event);
break;
}
}//end-if-select
else if(m_curMode == MOVE && event->button() == Qt::LeftButton ) {
m_isMoving = false;
// define selection window (default was 3)
setSelectRegionWidth( 10 );
setSelectRegionHeight( 10 );
// perform the selection
select( event->pos() );
if( m_isMoving ) // redraw window
{ changed();
update();
}
else // if no point is selected, then regular action (rotation) will be performed
CGAL::QGLViewer::mousePressEvent(event);
}//end-if-move
else if( m_curMode == FINDNB
&& event->button() == Qt::LeftButton && modifiers == Qt::SHIFT ) {
if( m_pScene->m_dt.is_valid() && m_pScene->m_dt.dimension() == 3 )
m_isPress = true;
else
displayMessage( tr("There exists no triangulation yet.") );
}//end-if-findnb
else if( m_curMode == EMPTYSPH
&& event->button() == Qt::LeftButton && modifiers == Qt::SHIFT ) {
if( m_pScene->m_dt.is_valid() && m_pScene->m_dt.dimension() == 3 )
m_isPress = true;
else
displayMessage( tr("There exists no triangulation yet.") );
m_hasEmptyS = false;
}//end-if-emptyS
else
CGAL::QGLViewer::mousePressEvent(event);
}
void Viewer::mouseMoveEvent(QMouseEvent *event)
{
if( m_curMode == INSERT_PT && m_isMoving ) {
Vec pt;
if( computeIntersect( event->pos(), pt ) ) {
m_newPt = Point_3(pt.x, pt.y, pt.z);
// compute the conflict hole induced by point p
computeConflict( m_newPt );
// redraw
changed();
update();
}//end-if-compute
}//end-if-inspt
else if( m_curMode == SELECT && m_isPress ) {
// update multiple selection window
m_rectSel.setBottomRight( event->pos() );
// redraw
//changed(); updateGL();;
}//end-if-sel
else if( m_curMode == MOVE && m_isMoving ) {
Vec pt;
if( computeIntersect( event->pos(), pt ) ) {
// note: QList::operator[] return a modifiable reference;
// while QList::at return a const reference
// move_if_no_collision moves the point stored in v to pt
// if there is not already another vertex placed on pt,
// the triangulation is modified s.t. the new position of v is pt;
// otherwise, the vertex at point pt is returned.
Vertex_handle vh = m_pScene->m_dt.move_if_no_collision(
m_pScene->m_vhArray.at( m_vidMoving ),
Point_3( pt.x, pt.y, pt.z ) );
int id1 = m_pScene->m_vhArray.indexOf( vh );
int id2 = m_pScene->m_vhArray.indexOf( vh, m_vidMoving+1 );
// remove the duplicate in vhArray
if( id1 != m_vidMoving )
m_pScene->m_vhArray.removeAt( id1 );
else if( id2 != -1 )
m_pScene->m_vhArray.removeAt( id2 );
m_pScene->m_vhArray[m_vidMoving] = vh;
}//end-if-compute
// redraw
// changed(); updateGL();;
}//end-if-move
else
CGAL::QGLViewer::mouseMoveEvent(event);
}
void Viewer::mouseReleaseEvent(QMouseEvent *event)
{
/* INS_V mode - Shift+Left: compute and insert a vertex */
if( m_curMode == INSERT_V && m_isPress ) {
m_isPress = false;
Vec pt;
if( computeIntersect( event->pos(), pt ) ) {
m_pScene->m_vhArray.push_back( m_pScene->m_dt.insert( Point_3( pt.x, pt.y, pt.z ) ) );
}//end-if-compute
// redraw
changed();
update();
}//end-if-ins
/* INS_PT mode - Shift+Left: compute and insert a point */
else if( m_curMode == INSERT_PT && m_isPress ) {
m_isPress = false;
Vec pt;
if( computeIntersect( event->pos(), pt ) ) {
m_hasNewPt = true;
m_newPt = Point_3(pt.x, pt.y, pt.z);
// compute the conflict hole induced by point p
computeConflict( m_newPt );
}//end-if-compute
// redraw
changed();
update();
}//end-if-inspt
/* INS_PT mode - Left: compute and insert a point */
else if( m_curMode == INSERT_PT && m_isMoving ) {
m_isMoving = false;
Vec pt;
if( computeIntersect( event->pos(), pt ) ) {
m_newPt = Point_3(pt.x, pt.y, pt.z);
// compute the conflict hole induced by point p
computeConflict( m_newPt );
}//end-if-compute
// redraw
changed();
update();
}//end-if-inspt
/* SEL mode - Left: terminate multiple point selection */
else if( m_curMode == SELECT && m_isPress ) {
// might swap left/right and top/bottom to make rectanle valid
m_rectSel = m_rectSel.normalized();
if( m_rectSel.width() == 1 && m_rectSel.height() == 1 ) { /* select a point */
// set a default selection window
setSelectRegionWidth( 10 );
setSelectRegionHeight( 10 );
// compute rectangle center and perform selection
select( m_rectSel.center() );
if( m_isPress ) {
m_isPress = false;
} else {
displayMessage( tr("No point is selected.") );
}
} else { /* select multiple points, i.e. selection window > 1 */
// define selection window
if( m_rectSel.width() < 10 )
setSelectRegionWidth( 10 );
else
setSelectRegionWidth( m_rectSel.width() );
if( m_rectSel.height() < 10 )
setSelectRegionHeight( 10 );
else
setSelectRegionHeight( m_rectSel.height() );
// compute rectangle center and perform selection
select( m_rectSel.center() );
if( m_isPress ) {
m_isPress = false;
displayMessage( QString::number(m_vidSeled.size()) + tr(" points are selected") );
} else { // empty window will cancel the current selection
for(QList<int>::iterator iit = m_vidSeled.begin(); iit < m_vidSeled.end(); ++iit)
m_pScene->m_vhArray.at(*iit)->setSeled( false );
m_vidSeled.clear();
}
}//end-if-selwindow
// update display to show
changed();
update();
}//end-if-select
/* MOVE mode - Left: terminate point moving */
else if( m_curMode == MOVE && m_isMoving ) {
Vec pt;
if( computeIntersect( event->pos(), pt ) ) {
// note: QList::operator[] return a modifiable reference;
// while QList::at return a const reference
// move_if_no_collision moves the point stored in v to pt
// if there is not already another vertex placed on pt,
// the triangulation is modified s.t. the new position of v is pt;
// otherwise, the vertex at point pt is returned.
Vertex_handle vh = m_pScene->m_dt.move_if_no_collision(
m_pScene->m_vhArray.at( m_vidMoving ),
Point_3( pt.x, pt.y, pt.z ) );
int id1 = m_pScene->m_vhArray.indexOf( vh );
int id2 = m_pScene->m_vhArray.indexOf( vh, m_vidMoving+1 );
// remove the duplicate in vhArray
if( id1 != m_vidMoving )
m_pScene->m_vhArray.removeAt( id1 );
else if( id2 != -1 )
m_pScene->m_vhArray.removeAt( id2 );
m_pScene->m_vhArray[m_vidMoving] = vh;
}//end-if-compute
// redraw
changed();
update();
}//end-if-move
/* FindNb mode - Shift+Left: find the nearest neighbor of the point */
else if( m_curMode == FINDNB && m_isPress ) {
m_isPress = false;
Vec pt;
if( computeIntersect( event->pos(), pt ) ) {
m_queryPt = Point_3( pt.x, pt.y, pt.z );
m_nearestNb = m_pScene->m_dt.nearest_vertex( m_queryPt );
}//end-if-compute
// redraw
changed();
update();
}//end-if-findnb
/* EmptySphere mode - Shift+Left: show the empty sphere of the cell */
else if( m_curMode == EMPTYSPH && m_isPress ) {
m_isPress = false;
Vec pt;
m_hasEmptyS = computeIntersect( event->pos(), pt );
if( m_hasEmptyS ) {
m_queryPt = Point_3( pt.x, pt.y, pt.z );
// find the cell that contains point p in its interior
m_cellContain = m_pScene->m_dt.locate( m_queryPt );
// show error if point is outside the convex hull
if( m_pScene->m_dt.is_infinite( m_cellContain ) ) {
m_hasEmptyS = false;
displayMessage( tr("Query point is outside the convex hull!") );
} else { /* compute the empty sphere */
// find the circumcenter of the four vertices of c
m_centerPt = m_pScene->m_dt.dual( m_cellContain );
// compute the radius of the empty sphere
m_fREmptyS = sqrt( CGAL::squared_distance( m_centerPt,
m_cellContain->vertex(0)->point() ) );
}
}//end-if-compute
// redraw
changed();
update();
}//end-if-emptysphere
else
CGAL::QGLViewer::mouseReleaseEvent(event);
}
void Viewer::wheelEvent(QWheelEvent *event)
{
// Get event modifiers key
const Qt::KeyboardModifiers modifiers = event->modifiers();
if( (m_curMode == INSERT_V || m_curMode == FINDNB || m_curMode == EMPTYSPH )
&& modifiers == Qt::SHIFT ) {
// delta() returns the distance that the wheel is rotated, in eighths of a degree.
// note: most mouse types work in steps of 15 degrees
// positive value: rotate forwards away from the user;
// negative value: rotate backwards toward the user.
m_fRadius += (event->angleDelta().y()*1.f / m_iStep ); // inc-/decrease by 0.1 per step
if( m_fRadius < 0.1f )
m_fRadius = 0.1f;
// redraw
changed();
update();
}//end-if-insv
else if( m_curMode == INSERT_PT && modifiers == Qt::SHIFT ) {
// delta() returns the distance that the wheel is rotated, in eighths of a degree.
// note: most mouse types work in steps of 15 degrees
// positive value: rotate forwards away from the user;
// negative value: rotate backwards toward the user.
float origR = m_fRadius;
m_fRadius += (event->angleDelta().y()*1.f / m_iStep ); // inc-/decrease by 0.1 per step
if( m_fRadius < 0.1f )
m_fRadius = 0.1f;
// update the new point and its conflict region
if( m_hasNewPt ) {
origR = m_fRadius / origR;
m_newPt = Point_3( m_newPt.x()*origR, m_newPt.y()*origR, m_newPt.z()*origR );
// compute the conflict hole induced by point p
computeConflict( m_newPt );
}//end-if-conflict
// redraw
changed();
update();
}//end-if-inspt
// resize the trackball when moving a point
else if( m_curMode == MOVE && modifiers == Qt::SHIFT && m_isMoving ) {
float origR = m_fRadius;
m_fRadius += (event->angleDelta().y()*1.f / m_iStep ); // inc-/decrease by 0.1 per step
if( m_fRadius < 0.1f )
m_fRadius = 0.1f;
origR = m_fRadius / origR;
Point_3 pt = m_pScene->m_vhArray.at( m_vidMoving )->point();
// note: QList::operator[] return a modifiable reference;
// while QList::at return a const reference
// move_if_no_collision moves the point stored in v to pt
// if there is not already another vertex placed on pt,
// the triangulation is modified s.t. the new position of v is pt;
// otherwise, the vertex at point pt is returned.
Vertex_handle vh = m_pScene->m_dt.move_if_no_collision(
m_pScene->m_vhArray.at( m_vidMoving ),
Point_3( pt.x()*origR, pt.y()*origR, pt.z()*origR ) );
int id1 = m_pScene->m_vhArray.indexOf( vh );
int id2 = m_pScene->m_vhArray.indexOf( vh, m_vidMoving+1 );
// remove the duplicate in vhArray
if( id1 != m_vidMoving )
m_pScene->m_vhArray.removeAt( id1 );
else if( id2 != -1 )
m_pScene->m_vhArray.removeAt( id2 );
m_pScene->m_vhArray[m_vidMoving] = vh;
// redraw
changed();
update();
}//end-if-move
else
CGAL::QGLViewer::wheelEvent(event);
}
void Viewer::keyPressEvent(QKeyEvent *event)
{
// Get event modifiers key
const Qt::KeyboardModifiers modifiers = event->modifiers();
/* Insert the newly inserted point as a vertex */
if( m_curMode == INSERT_PT && m_hasNewPt
&& ( event->key()==Qt::Key_Return || event->key()==Qt::Key_Enter )
&& modifiers==Qt::NoButton ) {
Facet& f = m_boundaryFacets.first(); // a boundary facet, i.e. a pair (cell_handle, i)
// insert_in_hole will create a new vertex by starring a hole
// i.e. delete all conflict cells, create a new vertex,
// and for each boundary facet, create a new cell with the new vertex
// it takes in an iterator range of conflict cells which specifies a hole
// and (begin, i) is a boundary facet that begin is one of the conflict cell
// but begin->neighbor(i) is not
// it returns the handle of the new vertex
m_pScene->m_vhArray.push_back( m_pScene->m_dt.insert_in_hole( m_newPt, // the point
m_conflictCells.begin(), // cell_begin
m_conflictCells.end(), // cell_end
f.first, // cell_handle begin
f.second ) ); // integer i
m_hasNewPt = false;
// erase old conflict hole info
m_boundaryFacets.clear();
m_conflictCells.clear();
// redraw
changed();
update();
}//end-if-insVertex
/* Cancel the newly inserted point and its conflict region */
else if( m_curMode == INSERT_PT && m_hasNewPt
&& event->key()==Qt::Key_Escape && modifiers==Qt::NoButton ) {
m_hasNewPt = false;
// erase old conflict hole info
m_boundaryFacets.clear();
m_conflictCells.clear();
// redraw
changed();
update();
}//end-if-escapeIns
/* Delete selected points */
else if( m_curMode == SELECT
&& event->key()==Qt::Key_Delete && modifiers==Qt::NoButton ) {
// sort selected id's in descending order
std::sort(m_vidSeled.begin(), m_vidSeled.end(), std::greater<int>());
for(QList<int>::iterator vit=m_vidSeled.begin(); vit<m_vidSeled.end(); ++vit) {
// remove the selected point from DT and vertex_handle_array
// note: QList::takeAt will removes the item at index position i and returns it.
m_pScene->m_dt.remove( m_pScene->m_vhArray.takeAt( *vit ) );
}
// clear the selection buffer
m_vidSeled.clear();
// redraw
changed();
update();
}//end-if-del
/* Cancel the selection */
else if( m_curMode == SELECT
&& event->key()==Qt::Key_Escape && modifiers==Qt::NoButton ) {
// clear the selection buffer
for(QList<int>::iterator iit=m_vidSeled.begin(); iit<m_vidSeled.end(); ++iit) {
m_pScene->m_vhArray.at(*iit)->setSeled( false );
}
m_vidSeled.clear();
// redraw
changed();
update();
}//end-if-escapeSel
/* Show/hide the trackball when drawing the empty sphere */
else if( m_curMode == EMPTYSPH
&& event->key()==Qt::Key_S && modifiers==Qt::NoButton ) {
m_showTrackball = !m_showTrackball;
// redraw
changed();
update();
}//end-if-showBall
else
CGAL::QGLViewer::keyPressEvent(event);
// redraw
changed();
update();
}
/*************************************************************/
/* Computation functions */
bool Viewer::computeIntersect( const QPoint & pos, Vec & pt )
{
Vec eye, dir;
// Compute eye position and direction to the clicked point,
// used to draw a representation of the intersecting line
camera()->convertClickToLine( pos, eye, dir );
// Compute the intersection point with the sphere
// note that the center of the sphere is at the origin (0, 0, 0)
// thus, (1) pt = eye + t*dir and (2) dist( pt, origin ) = radius
// i.e. (x_eye + t*x_dir)^2 + (y_eye + t*y_dir)^2 + (z_eye + t*z_dir)^2 = r^2
// --> t^2( dir*dir ) + 2t( eye*dir ) + eye*eye - r^2 = 0
// where "dir*dir" is the dot product of vector dir
// we need to solve t and the smaller t (nearer to eye position) is what we want
float a = dir*dir;
float b = eye*dir;
float c = eye*eye - m_fRadius*m_fRadius;
float delta = b*b - a*c;
if( delta < 0 ) {
displayMessage( tr("Point is not on the sphere!") );
return false;
} else {
float t = ( (-1.)*b - sqrt(delta) ) / a;
pt = eye + t*dir;
return true;
}
}
void Viewer::computeConflict( Point_3 pt )
{
// find the cell that contains point p in its interior
m_cellContain = m_pScene->m_dt.locate( pt );
// erase old conflict hole info
m_boundaryFacets.clear();
m_conflictCells.clear();
// show msg if point is outside the convex hull
if( m_pScene->m_dt.is_infinite( m_cellContain ) )
displayMessage( tr("Note: point is outside the convex hull.") );
// compute the conflict hole induced by point p
m_pScene->m_dt.find_conflicts( pt, // the point
m_cellContain, // starting cell that must be in conflict
std::back_inserter(m_boundaryFacets), // the facets on the boundary
std::back_inserter(m_conflictCells) ); // the cells in conflict
}
/*************************************************************/
/* Animation functions */
void Viewer::toggleIncremental(bool on) {
if( on ) { // play
if( m_incrementalPts.isEmpty() ) {
/* start play */
if( m_pScene->m_dt.number_of_vertices() == 0 ) {
CGAL::Random_points_in_cube_3<Point_3> pts_generator(1.0);
std::copy_n( pts_generator, 100, std::back_inserter(m_incrementalPts) );
} else {
for(QList<Vertex_handle>::iterator vit = m_pScene->m_vhArray.begin();
vit < m_pScene->m_vhArray.end(); ++vit) {
m_incrementalPts.push_back( (*vit)->point() );
}//end-for
// erase existing vertices
initClean();
}//end-if-pts
// sorts points in a way that improves space locality
CGAL::spatial_sort( m_incrementalPts.begin(), m_incrementalPts.end() );
// set the current to "highlight the new point"
m_curStep = INIT;
}/* else resume play */
// set up the timer
m_pTimer->start(1000);
} else { // pause
m_pTimer->stop();
}
// redraw
changed();
update();
}
void Viewer::stopIncremental() {
if( !m_incrementalPts.isEmpty() ) {
// will call toggleIncremental to stop the timer
Q_EMIT( stopIncAnimation() );
// insert the rest points
for(QList<Point_3>::iterator pit=m_incrementalPts.begin();
pit < m_incrementalPts.end(); ++pit) {
Vertex_handle hint;
if( m_pScene->m_vhArray.isEmpty() ) {
hint = m_pScene->m_dt.insert( *pit );
} else {
hint = m_pScene->m_vhArray.last();
hint = m_pScene->m_dt.insert( *pit, hint );
}
m_pScene->m_vhArray.push_back( hint );
}
m_incrementalPts.clear();
}
// redraw
changed();
update();
}
void Viewer::incremental_insert() {
Vertex_handle hint;
if( !m_incrementalPts.isEmpty() ) {
switch( m_curStep ) {
case INIT: // end of INIT: get the next-to-insert point
m_curIncPt = m_incrementalPts.at(0);
m_curStep = NEWPT;
break;
case NEWPT: // end of NEWPT: locate the cell containing the point
if( m_pScene->m_dt.is_valid() && m_pScene->m_dt.dimension() == 3 ) {
computeConflict( m_curIncPt );
m_curStep = CELL;
}
else {
// popup the first point and insert it
m_curIncPt = m_incrementalPts.takeFirst();
if( m_pScene->m_vhArray.isEmpty() ) {
hint = m_pScene->m_dt.insert( m_curIncPt );
}
else {
hint = m_pScene->m_vhArray.last();
hint = m_pScene->m_dt.insert( m_curIncPt, hint );
}
m_pScene->m_vhArray.push_back( hint );
m_curStep = INIT;
}
break;
case CELL: // end of CELL: compute the conflict region
m_curStep = CONFLICT;
break;
case CONFLICT: // end of CONFLICT: do the insertion and go back to INIT
// popup the first point and insert it
m_curIncPt = m_incrementalPts.takeFirst();
if( m_pScene->m_vhArray.isEmpty() ) {
hint = m_pScene->m_dt.insert( m_curIncPt );
} else {
hint = m_pScene->m_vhArray.last();
hint = m_pScene->m_dt.insert( m_curIncPt, hint );
}
m_pScene->m_vhArray.push_back( hint );
m_curStep = INIT;
break;
}//end-of-switch
} else {
/* if finished, then start over */
for(QList<Vertex_handle>::iterator vit = m_pScene->m_vhArray.begin();
vit < m_pScene->m_vhArray.end(); ++vit) {
m_incrementalPts.push_back( (*vit)->point() );
}//end-for
// erase existing vertices
initClean();
// set the current to "highlight the new point"
m_curStep = INIT;
}
// redraw
changed();
update();
}
void Viewer::draw_cylinder(float R, int prec, Coords_ptr& vertices, Coords_ptr& normals)
{
vertices->resize(0);
normals->resize(0);
//body of the cylinder
for(int d = 0; d<360; d+= 360/prec)
{
//point A1
float D = d*CGAL_PI/180.0;
vertices->push_back(R * sin(D));
vertices->push_back(0);
vertices->push_back(R * cos(D));
normals->push_back(sin(D));
normals->push_back(0);
normals->push_back(cos(D));
//point B1
vertices->push_back(R * sin(D));
vertices->push_back(1);
vertices->push_back(R * cos(D));
normals->push_back(sin(D));
normals->push_back(0);
normals->push_back(cos(D));
//point C1
D = (d+360/prec)*CGAL_PI/180.0;
vertices->push_back(R * sin(D));
vertices->push_back(1);
vertices->push_back(R * cos(D));
normals->push_back(sin(D));
normals->push_back(0);
normals->push_back(cos(D));
//point A2
D = (d+360/prec)*CGAL_PI/180.0;
vertices->push_back(R * sin(D));
vertices->push_back(1);
vertices->push_back(R * cos(D));
normals->push_back(sin(D));
normals->push_back(0);
normals->push_back(cos(D));
//point B2
vertices->push_back(R * sin(D));
vertices->push_back(0);
vertices->push_back(R * cos(D));
normals->push_back(sin(D));
normals->push_back(0);
normals->push_back(cos(D));
//point C2
D = d*CGAL_PI/180.0;
vertices->push_back(R * sin(D));
vertices->push_back(0);
vertices->push_back(R * cos(D));
normals->push_back(sin(D));
normals->push_back(0);
normals->push_back(cos(D));
}
}
void Viewer::draw_sphere(float R, int prec, Coords_ptr& vertices, Coords_ptr& normals)
{
vertices->resize(0);
normals->resize(0);
int rings=180/prec, sectors=360/prec;
float T, P;
float x[4],y[4],z[4];
//Top of the sphere
for(int t=0; t<360; t+=sectors)
{
vertices->push_back(0);
vertices->push_back(0);
vertices->push_back(R);
normals->push_back(0);
normals->push_back(0);
normals->push_back(1);
P = rings*CGAL_PI/180.0;
T = t*CGAL_PI/180.0;
x[1] = sin(P) * cos(T) ;
y[1] = sin(P) * sin(T) ;
z[1] = cos(P);
vertices->push_back(R * x[1]);
vertices->push_back(R * y[1]);
vertices->push_back(R * z[1]);
normals->push_back(x[1]);
normals->push_back(y[1]);
normals->push_back(z[1]);
//
P = rings*CGAL_PI/180.0;
T = (t+sectors)*CGAL_PI/180.0;
x[2] = sin(P) * cos(T) ;
y[2] = sin(P) * sin(T) ;
z[2] = cos(P);
vertices->push_back(R * x[2]);
vertices->push_back(R * y[2]);
vertices->push_back(R * z[2]);
normals->push_back(x[2]);
normals->push_back(y[2]);
normals->push_back(z[2]);
}
//Body of the sphere
for (int p=rings; p<180-rings; p+=rings)
for(int t=0; t<360; t+=sectors)
{
//A
P = p*CGAL_PI/180.0;
T = t*CGAL_PI/180.0;
x[0] = sin(P) * cos(T) ;
y[0] = sin(P) * sin(T) ;
z[0] = cos(P);
vertices->push_back(R * x[0]);
vertices->push_back(R * y[0]);
vertices->push_back(R * z[0]);
normals->push_back(x[0]);
normals->push_back(y[0]);
normals->push_back(z[0]);
//B
P = (p+rings)*CGAL_PI/180.0;
T = t*CGAL_PI/180.0;
x[1] = sin(P) * cos(T) ;
y[1] = sin(P) * sin(T) ;
z[1] = cos(P);
vertices->push_back(R * x[1]);
vertices->push_back(R * y[1]);
vertices->push_back(R * z[1]);
normals->push_back(x[1]);
normals->push_back(y[1]);
normals->push_back(z[1]);
//C
P = p*CGAL_PI/180.0;
T = (t+sectors)*CGAL_PI/180.0;
x[2] = sin(P) * cos(T) ;
y[2] = sin(P) * sin(T) ;
z[2] = cos(P);
vertices->push_back(R * x[2]);
vertices->push_back(R * y[2]);
vertices->push_back(R * z[2]);
normals->push_back(x[2]);
normals->push_back(y[2]);
normals->push_back(z[2]);
//D
P = (p+rings)*CGAL_PI/180.0;
T = (t+sectors)*CGAL_PI/180.0;
x[3] = sin(P) * cos(T) ;
y[3] = sin(P) * sin(T) ;
z[3] = cos(P);
vertices->push_back(R * x[3]);
vertices->push_back(R * y[3]);
vertices->push_back(R * z[3]);
normals->push_back(x[3]);
normals->push_back(y[3]);
normals->push_back(z[3]);
vertices->push_back(R * x[1]);
vertices->push_back(R * y[1]);
vertices->push_back(R * z[1]);
normals->push_back(x[1]);
normals->push_back(y[1]);
normals->push_back(z[1]);
vertices->push_back(R * x[2]);
vertices->push_back(R * y[2]);
vertices->push_back(R * z[2]);
normals->push_back(x[2]);
normals->push_back(y[2]);
normals->push_back(z[2]);
}
//Bottom of the sphere
for(int t=0; t<360; t+=sectors)
{
vertices->push_back(0);
vertices->push_back(0);
vertices->push_back(-R);
normals->push_back(0);
normals->push_back(0);
normals->push_back(-1);
P = (180-rings)*CGAL_PI/180.0;
T = t*CGAL_PI/180.0;
x[1] = sin(P) * cos(T) ;
y[1] = sin(P) * sin(T) ;
z[1] = cos(P);
vertices->push_back(R * x[1]);
vertices->push_back(R * y[1]);
vertices->push_back(R * z[1]);
normals->push_back(x[1]);
normals->push_back(y[1]);
normals->push_back(z[1]);
P = (180-rings)*CGAL_PI/180.0;
T = (t+sectors)*CGAL_PI/180.0;
x[2] = sin(P) * cos(T) ;
y[2] = sin(P) * sin(T) ;
z[2] = cos(P);
vertices->push_back(R * x[2]);
vertices->push_back(R * y[2]);
vertices->push_back(R * z[2]);
normals->push_back(x[2]);
normals->push_back(y[2]);
normals->push_back(z[2]);
}
}