#include "Viewer.h" #include #include #include #include #include Viewer::Viewer(QWidget* parent ) : CGAL::QGLViewer(parent) { extension_is_found = false; } Viewer::~Viewer() { makeCurrent(); for(int i=0; i<3; ++i) vao[i].destroy(); for(int i=0; i<9; ++i) buffers[i].destroy(); } void Viewer::compile_shaders() { initializeOpenGLFunctions(); if(! buffers[0].create() || !buffers[1].create() || !buffers[2].create() || !buffers[3].create() || !buffers[4].create() || !buffers[4].create() || !buffers[5].create() || !buffers[6].create() || !buffers[7].create() || !buffers[8].create()) { std::cerr<<"VBO Creation FAILED"<compileSourceCode(vertex_source)) { std::cerr<<"Compiling vertex source FAILED"<compileSourceCode(fragment_source)) { std::cerr<<"Compiling fragmentsource FAILED"<compileSourceCode(vertex_source_no_ext)) { std::cerr<<"Compiling vertex source FAILED"<compileSourceCode(fragment_source_no_ext)) { std::cerr<<"Compiling fragmentsource FAILED"<(pos_sphere.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); buffers[0].release(); //normals of the sphere buffers[1].bind(); buffers[1].allocate(normals.data(), static_cast(normals.size()*sizeof(float))); normalsLocation[0] = rendering_program.attributeLocation("normal"); rendering_program.bind(); rendering_program.enableAttributeArray(normalsLocation[0]); rendering_program.setAttributeBuffer(normalsLocation[0],GL_FLOAT,0,3); buffers[1].release(); //center of the sphere buffers[2].bind(); buffers[2].allocate(trivial_center.data(), static_cast(trivial_center.size()*sizeof(float))); trivialCenterLocation = rendering_program.attributeLocation("center"); rendering_program.bind(); rendering_program.enableAttributeArray(trivialCenterLocation); rendering_program.setAttributeBuffer(trivialCenterLocation,GL_FLOAT,0,3); buffers[2].release(); if(extension_is_found) { glVertexAttribDivisor(trivialCenterLocation, 1); glVertexAttribDivisor(normalsLocation[0], 0); } vao[0].release(); //The circles vao[1].bind(); buffers[3].bind(); buffers[3].allocate(pos_lines.data(), static_cast(pos_lines.size()*sizeof(float))); vertexLocation[2] = rendering_program.attributeLocation("vertex"); rendering_program.bind(); rendering_program.enableAttributeArray(vertexLocation[2]); rendering_program.setAttributeBuffer(vertexLocation[2],GL_FLOAT,0,3); buffers[3].release(); //normals buffers[4].bind(); buffers[4].allocate(normals_lines.data(), static_cast(normals_lines.size()*sizeof(float))); normalsLocation[1] = rendering_program.attributeLocation("normal"); rendering_program.bind(); rendering_program.enableAttributeArray(normalsLocation[1]); rendering_program.setAttributeBuffer(normalsLocation[1],GL_FLOAT,0,3); buffers[4].release(); //center buffers[5].bind(); buffers[5].allocate(trivial_center.data(), static_cast(trivial_center.size()*sizeof(float))); trivialCenterLocation = rendering_program.attributeLocation("center"); rendering_program.bind(); rendering_program.enableAttributeArray(trivialCenterLocation); rendering_program.setAttributeBuffer(trivialCenterLocation,GL_FLOAT,0,3); buffers[5].release(); if(extension_is_found) { glVertexAttribDivisor(trivialCenterLocation, 1); glVertexAttribDivisor(normalsLocation[0], 0); } rendering_program.release(); vao[1].release(); //The little green spheres vao[2].bind(); if(extension_is_found) { //points of the spheres buffers[6].bind(); buffers[6].allocate(pos_sphere_inter.data(), static_cast(pos_sphere_inter.size()*sizeof(float))); vertexLocation[2] = rendering_program.attributeLocation("vertex"); rendering_program.bind(); rendering_program.enableAttributeArray(vertexLocation[2]); rendering_program.setAttributeBuffer(vertexLocation[2],GL_FLOAT,0,3); buffers[6].release(); //normals of the sphere buffers[7].bind(); buffers[7].allocate(normals_inter.data(), static_cast(normals_inter.size()*sizeof(float))); normalsLocation[2] = rendering_program.attributeLocation("normal"); rendering_program.bind(); rendering_program.enableAttributeArray(normalsLocation[2]); rendering_program.setAttributeBuffer(normalsLocation[2],GL_FLOAT,0,3); buffers[7].release(); //center of the sphere buffers[8].bind(); buffers[8].allocate(pos_points.data(), static_cast(pos_points.size()*sizeof(float))); centerLocation = rendering_program.attributeLocation("center"); rendering_program.bind(); rendering_program.enableAttributeArray(centerLocation); rendering_program.setAttributeBuffer(centerLocation,GL_FLOAT,0,3); buffers[8].release(); glVertexAttribDivisor(centerLocation, 1); glVertexAttribDivisor(normalsLocation[1], 0); } else { //points of the sphere buffers[6].bind(); buffers[6].allocate(pos_points.data(), static_cast(pos_points.size()*sizeof(float))); rendering_program_no_ext.bind(); rendering_program_no_ext.enableAttributeArray("vertex"); rendering_program_no_ext.setAttributeBuffer("vertex",GL_FLOAT,0,3); buffers[6].release(); } vao[2].release(); } void Viewer::compute_elements() { //The Central Sphere { pos_sphere.resize(0); trivial_center.resize(0); int rings=3,sectors=6; float T, P, R = 0.999f; float x[4],y[4],z[4]; //Top of the sphere for(int t=0; t<360; t+=sectors) { pos_sphere.push_back(0); pos_sphere.push_back(0); pos_sphere.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); pos_sphere.push_back(R * x[1]); pos_sphere.push_back(R * y[1]); pos_sphere.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); pos_sphere.push_back(R * x[2]); pos_sphere.push_back(R * y[2]); pos_sphere.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); pos_sphere.push_back(R * x[0]); pos_sphere.push_back(R * y[0]); pos_sphere.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); pos_sphere.push_back(R * x[1]); pos_sphere.push_back(R * y[1]); pos_sphere.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); pos_sphere.push_back(R * x[2]); pos_sphere.push_back(R * y[2]); pos_sphere.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); pos_sphere.push_back(R * x[3]); pos_sphere.push_back(R * y[3]); pos_sphere.push_back(R * z[3]); normals.push_back(x[3]); normals.push_back(y[3]); normals.push_back(z[3]); pos_sphere.push_back(R * x[1]); pos_sphere.push_back(R * y[1]); pos_sphere.push_back(R * z[1]); normals.push_back(x[1]); normals.push_back(y[1]); normals.push_back(z[1]); pos_sphere.push_back(R * x[2]); pos_sphere.push_back(R * y[2]); pos_sphere.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) { pos_sphere.push_back(0); pos_sphere.push_back(0); pos_sphere.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); pos_sphere.push_back(R * x[1]); pos_sphere.push_back(R * y[1]); pos_sphere.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); pos_sphere.push_back(R * x[2]); pos_sphere.push_back(R * y[2]); pos_sphere.push_back(R * z[2]); normals.push_back(x[2]); normals.push_back(y[2]); normals.push_back(z[2]); } trivial_center.push_back(0.0);trivial_center.push_back(0.0);trivial_center.push_back(0.0); } //The intersection spheres { pos_sphere_inter.resize(0); int rings=3,sectors=3; float T, P, R = 0.005f; float x[4],y[4],z[4]; //Top of the sphere for(int t=0; t<360; t+=sectors) { pos_sphere_inter.push_back(0); pos_sphere_inter.push_back(0); pos_sphere_inter.push_back(R); normals_inter.push_back(0); normals_inter.push_back(0); normals_inter.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); pos_sphere_inter.push_back(R * x[1]); pos_sphere_inter.push_back(R * y[1]); pos_sphere_inter.push_back(R * z[1]); normals_inter.push_back(x[1]); normals_inter.push_back(y[1]); normals_inter.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); pos_sphere_inter.push_back(R * x[2]); pos_sphere_inter.push_back(R * y[2]); pos_sphere_inter.push_back(R * z[2]); normals_inter.push_back(x[2]); normals_inter.push_back(y[2]); normals_inter.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); pos_sphere_inter.push_back(R * x[0]); pos_sphere_inter.push_back(R * y[0]); pos_sphere_inter.push_back(R * z[0]); normals_inter.push_back(x[0]); normals_inter.push_back(y[0]); normals_inter.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); pos_sphere_inter.push_back(R * x[1]); pos_sphere_inter.push_back(R * y[1]); pos_sphere_inter.push_back(R * z[1]); normals_inter.push_back(x[1]); normals_inter.push_back(y[1]); normals_inter.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); pos_sphere_inter.push_back(R * x[2]); pos_sphere_inter.push_back(R * y[2]); pos_sphere_inter.push_back(R * z[2]); normals_inter.push_back(x[2]); normals_inter.push_back(y[2]); normals_inter.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); pos_sphere_inter.push_back(R * x[3]); pos_sphere_inter.push_back(R * y[3]); pos_sphere_inter.push_back(R * z[3]); normals_inter.push_back(x[3]); normals_inter.push_back(y[3]); normals_inter.push_back(z[3]); pos_sphere_inter.push_back(R * x[1]); pos_sphere_inter.push_back(R * y[1]); pos_sphere_inter.push_back(R * z[1]); normals_inter.push_back(x[1]); normals_inter.push_back(y[1]); normals_inter.push_back(z[1]); pos_sphere_inter.push_back(R * x[2]); pos_sphere_inter.push_back(R * y[2]); pos_sphere_inter.push_back(R * z[2]); normals_inter.push_back(x[2]); normals_inter.push_back(y[2]); normals_inter.push_back(z[2]); } //Bottom of the sphere for(int t=0; t<360; t+=sectors) { pos_sphere_inter.push_back(0); pos_sphere_inter.push_back(0); pos_sphere_inter.push_back(-R); normals_inter.push_back(0); normals_inter.push_back(0); normals_inter.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); pos_sphere_inter.push_back(R * x[1]); pos_sphere_inter.push_back(R * y[1]); pos_sphere_inter.push_back(R * z[1]); normals_inter.push_back(x[1]); normals_inter.push_back(y[1]); normals_inter.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); pos_sphere_inter.push_back(R * x[2]); pos_sphere_inter.push_back(R * y[2]); pos_sphere_inter.push_back(R * z[2]); normals_inter.push_back(x[2]); normals_inter.push_back(y[2]); normals_inter.push_back(z[2]); } } //init { pos_points.resize(0); pos_lines.resize(0); //random generator of points within a sphere typedef CGAL::Creator_uniform_3 Creator; CGAL::Random_points_in_sphere_3 gen; const unsigned nb_circles=20; //vector to store input points std::vector points; points.reserve(nb_circles); for (unsigned i=0;i intersections; naive_compute_intersection_points(points,std::back_inserter(intersections)); //draw points as small spheres for (std::vector::const_iterator it=intersections.begin();it!=intersections.end();++it){ pos_points.push_back(it->x()); pos_points.push_back(it->y()); pos_points.push_back(it->z()); } } } 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 ambient(0.1f, 0.1f, 0.1f, 1.0f); QVector4D diffuse( 0.9f, 0.9f, 0.9f, 0.0f ); QVector4D specular( 0.0f, 0.0f, 0.0f, 0.0f ); QVector4D position( -1.2f, 1.2f, .9797958971f, 1.0f ); GLfloat shininess = 1.0f; rendering_program.bind(); mvpLocation = rendering_program.uniformLocation("mvp_matrix"); mvLocation = rendering_program.uniformLocation("mv_matrix"); colorLocation = rendering_program.uniformLocation("color"); 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, mvpMatrix); rendering_program.setUniformValue(mvLocation, mvMatrix); rendering_program.release(); if(!extension_is_found) { rendering_program_no_ext.bind(); rendering_program_no_ext.setUniformValue("mvp_matrix", mvpMatrix); rendering_program_no_ext.release(); } } void Viewer::draw() { glEnable(GL_DEPTH_TEST); QColor color; //sphere vao[0].bind(); attrib_buffers(this); rendering_program.bind(); color.setRgbF(1.0f, 1.0f, 1.0f); rendering_program.setUniformValue(colorLocation, color); if(extension_is_found) glDrawArraysInstanced(GL_TRIANGLES, 0, static_cast(pos_sphere.size()/3), 1); else glDrawArrays(GL_TRIANGLES, 0, static_cast(pos_sphere.size()/3)); rendering_program.release(); vao[0].release(); //intersection vao[2].bind(); attrib_buffers(this); color.setRgbF(0.0f, 1.0f, 0.0f); if(extension_is_found) { rendering_program.bind(); rendering_program.setUniformValue(colorLocation, color); glDrawArraysInstanced(GL_TRIANGLES, 0, static_cast(pos_sphere_inter.size()/3), static_cast(pos_points.size()/3)); rendering_program.release(); } else { rendering_program_no_ext.bind(); rendering_program_no_ext.setUniformValue(colorLocation, color); glDrawArrays(GL_POINTS, 0, static_cast(pos_points.size()/3)); rendering_program_no_ext.release(); } vao[2].release(); //circles vao[1].bind(); attrib_buffers(this); rendering_program.bind(); color.setRgbF(1.0f, 0.0f, 0.0f); rendering_program.setUniformValue(colorLocation, color); glDrawArrays(GL_LINES, 0, static_cast(pos_lines.size()/3)); rendering_program.release(); vao[1].release(); } 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; compile_shaders(); compute_elements(); initialize_buffers(); glEnable(GL_BLEND); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_POINT_SMOOTH); glEnable(GL_LINE_SMOOTH); } template void Viewer::naive_compute_intersection_points(const std::vector& points,Output_iterator out) const { typedef CGAL::Exact_spherical_kernel_3 SK; SK::Sphere_3 sphere(SK::Point_3(0,0,0),1); //converter point to exact SK point type CGAL::Cartesian_converter to_exact; std::vector circles; //create circles from points: need to use a converter to change floating points coordinates into an exact NT. for (std::vector::const_iterator it=points.begin();it!=points.end();++it){ const SK::Point_3 center=to_exact(*it); circles.push_back( SK::Circle_3(sphere,SK::Plane_3(center,center-CGAL::ORIGIN) ) ); } //Look for intersection points among pair of circles: use a naive and quadratic way for (std::vector::const_iterator it_f=circles.begin();it_f!=--circles.end();++it_f){ std::vector::const_iterator it_s=it_f; ++it_s; for (;it_s!=circles.end();++it_s){ std::vector intersections; //ensure_circles are different CGAL_precondition(*it_s!=*it_f); CGAL::intersection(*it_f,*it_s,std::back_inserter(intersections)); if (!intersections.empty()){ for (std::vector ::const_iterator it_pt=intersections.begin();it_pt!=intersections.end();++it_pt){ const std::pair* pt= CGAL::object_cast< std::pair > (&(*it_pt)); assert(pt!=nullptr); *out++=EPIC::Point_3( CGAL::to_double(pt->first.x()), CGAL::to_double(pt->first.y()), CGAL::to_double(pt->first.z()) ); } } } } }