mirror of https://github.com/CGAL/cgal
914 lines
29 KiB
C++
914 lines
29 KiB
C++
#include "Viewer.h"
|
|
#include <CGAL/point_generators_3.h>
|
|
#include <CGAL/squared_distance_3.h>
|
|
#include <CGAL/Exact_spherical_kernel_3.h>
|
|
#include <vector>
|
|
#include <CGAL/Qt/CreateOpenGLContext.h>
|
|
|
|
|
|
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"<<std::endl;
|
|
}
|
|
|
|
if(!vao[0].create() || !vao[1].create() || !vao[2].create())
|
|
{
|
|
std::cerr<<"VAO Creation FAILED"<<std::endl;
|
|
}
|
|
|
|
//The sphere
|
|
|
|
//Vertex source code
|
|
const char vertex_source[] =
|
|
{
|
|
"#version 150 \n"
|
|
"in highp vec4 vertex;\n"
|
|
"in highp vec3 normal;\n"
|
|
"in highp vec4 center;\n"
|
|
|
|
"uniform highp mat4 mvp_matrix;\n"
|
|
"uniform highp mat4 mv_matrix; \n"
|
|
|
|
"out highp vec4 fP; \n"
|
|
"out 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"
|
|
"}"
|
|
};
|
|
//Vertex source code
|
|
const char fragment_source[] =
|
|
{
|
|
"#version 150 \n"
|
|
"in highp vec4 fP; \n"
|
|
"in 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"
|
|
"out highp vec4 out_color; \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 = max(dot(N,L), 0.0) * light_diff * color; \n"
|
|
" highp vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; \n"
|
|
|
|
"out_color = light_amb*color + diffuse ; \n"
|
|
"} \n"
|
|
"\n"
|
|
};
|
|
QOpenGLShader *vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex);
|
|
if(!vertex_shader->compileSourceCode(vertex_source))
|
|
{
|
|
std::cerr<<"Compiling vertex source FAILED"<<std::endl;
|
|
}
|
|
|
|
QOpenGLShader *fragment_shader= new QOpenGLShader(QOpenGLShader::Fragment);
|
|
if(!fragment_shader->compileSourceCode(fragment_source))
|
|
{
|
|
std::cerr<<"Compiling fragmentsource FAILED"<<std::endl;
|
|
}
|
|
|
|
if(!rendering_program.addShader(vertex_shader))
|
|
{
|
|
std::cerr<<"adding vertex shader FAILED"<<std::endl;
|
|
}
|
|
if(!rendering_program.addShader(fragment_shader))
|
|
{
|
|
std::cerr<<"adding fragment shader FAILED"<<std::endl;
|
|
}
|
|
if(!rendering_program.link())
|
|
{
|
|
std::cerr<<"linking Program FAILED"<<std::endl;
|
|
}
|
|
rendering_program.bind();
|
|
if(!extension_is_found)
|
|
{
|
|
|
|
|
|
//Vertex source code
|
|
const char vertex_source_no_ext[] =
|
|
{
|
|
"#version 150 \n"
|
|
"in highp vec4 vertex;\n"
|
|
"uniform highp mat4 mvp_matrix;\n"
|
|
"void main(void)\n"
|
|
"{\n"
|
|
" gl_PointSize = 4.0;\n"
|
|
" gl_Position = mvp_matrix * vertex;\n"
|
|
"}"
|
|
};
|
|
//Vertex source code
|
|
const char fragment_source_no_ext[] =
|
|
{
|
|
"#version 150 \n"
|
|
"uniform highp vec4 color; \n"
|
|
"out highp vec4 out_color; \n"
|
|
"void main(void) { \n"
|
|
"out_color = color; \n"
|
|
"} \n"
|
|
"\n"
|
|
};
|
|
vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex);
|
|
if(!vertex_shader->compileSourceCode(vertex_source_no_ext))
|
|
{
|
|
std::cerr<<"Compiling vertex source FAILED"<<std::endl;
|
|
}
|
|
|
|
fragment_shader= new QOpenGLShader(QOpenGLShader::Fragment);
|
|
if(!fragment_shader->compileSourceCode(fragment_source_no_ext))
|
|
{
|
|
std::cerr<<"Compiling fragmentsource FAILED"<<std::endl;
|
|
}
|
|
|
|
if(!rendering_program_no_ext.addShader(vertex_shader))
|
|
{
|
|
std::cerr<<"adding vertex shader FAILED"<<std::endl;
|
|
}
|
|
if(!rendering_program_no_ext.addShader(fragment_shader))
|
|
{
|
|
std::cerr<<"adding fragment shader FAILED"<<std::endl;
|
|
}
|
|
if(!rendering_program_no_ext.link())
|
|
{
|
|
std::cerr<<"linking Program FAILED"<<std::endl;
|
|
}
|
|
rendering_program_no_ext.bind();
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
void Viewer::initialize_buffers()
|
|
{
|
|
//The big white sphere
|
|
vao[0].bind();
|
|
//points of the sphere
|
|
buffers[0].bind();
|
|
buffers[0].allocate(pos_sphere.data(),
|
|
static_cast<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<EPIC::FT,EPIC::Point_3> Creator;
|
|
CGAL::Random_points_in_sphere_3<EPIC::Point_3, Creator> gen;
|
|
|
|
const unsigned nb_circles=20;
|
|
|
|
//vector to store input points
|
|
std::vector<EPIC::Point_3> points;
|
|
points.reserve(nb_circles);
|
|
|
|
|
|
|
|
for (unsigned i=0;i<nb_circles;++i){
|
|
EPIC::Point_3 p=*++gen;
|
|
//prevent great circles
|
|
while (p.x()==0 && p.y()==0 && p.z()==0) { p=*++gen; }
|
|
|
|
const EPIC::Point_3 origin(0,0,0);
|
|
const EPIC::Plane_3 plane(p, p-origin);
|
|
EPIC::Vector_3 base1=plane.base1();
|
|
EPIC::Vector_3 base2=plane.base2();
|
|
base1=base1/CGAL::sqrt(base1.squared_length());
|
|
base2=base2/CGAL::sqrt(base2.squared_length());
|
|
const double radius=CGAL::sqrt( CGAL::to_double( 1 - CGAL::squared_distance(origin,p) ) );
|
|
const double nb_pt_per_circle=100;
|
|
const double step=2 * CGAL_PI / nb_pt_per_circle;
|
|
|
|
for (double theta = 0; theta < 2 * CGAL_PI-step ; theta += step) {
|
|
const EPIC::Point_3 a=p + ( radius*cos(theta)*base1 + radius*sin(theta)*base2 );
|
|
const EPIC::Point_3 b=p + ( radius*cos(theta+step)*base1 + radius*sin(theta+step)*base2 );
|
|
pos_lines.push_back(a.x());pos_lines.push_back(a.y());pos_lines.push_back(a.z());
|
|
normals_lines.push_back(a.x());normals_lines.push_back(a.y());normals_lines.push_back(a.z());
|
|
pos_lines.push_back(b.x());pos_lines.push_back(b.y());pos_lines.push_back(b.z());
|
|
normals_lines.push_back(b.x());normals_lines.push_back(b.y());normals_lines.push_back(b.z());
|
|
|
|
}
|
|
points.push_back(p);
|
|
|
|
}
|
|
|
|
std::vector<EPIC::Point_3> intersections;
|
|
naive_compute_intersection_points(points,std::back_inserter(intersections));
|
|
|
|
//draw points as small spheres
|
|
for (std::vector<EPIC::Point_3>::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<GLsizei>(pos_sphere.size()/3), 1);
|
|
else
|
|
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(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<GLsizei>(pos_sphere_inter.size()/3), static_cast<GLsizei>(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<GLsizei>(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<GLsizei>(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<class Output_iterator>
|
|
void Viewer::naive_compute_intersection_points(const std::vector<EPIC::Point_3>& 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<EPIC,SK> to_exact;
|
|
std::vector<SK::Circle_3> circles;
|
|
|
|
//create circles from points: need to use a converter to change floating points coordinates into an exact NT.
|
|
for (std::vector<EPIC::Point_3>::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<SK::Circle_3>::const_iterator it_f=circles.begin();it_f!=--circles.end();++it_f){
|
|
std::vector<SK::Circle_3>::const_iterator it_s=it_f;
|
|
++it_s;
|
|
typedef std::pair<SK::Circular_arc_point_3,unsigned> Point_and_multiplicity;
|
|
for (;it_s!=circles.end();++it_s){
|
|
std::vector<Point_and_multiplicity> intersections;
|
|
//ensure_circles are different
|
|
CGAL_precondition(*it_s!=*it_f);
|
|
CGAL::intersection(*it_f,*it_s,CGAL::dispatch_or_drop_output<Point_and_multiplicity>(std::back_inserter(intersections)));
|
|
if (!intersections.empty()){
|
|
for (const Point_and_multiplicity& pt : intersections)
|
|
{
|
|
*out++=EPIC::Point_3( CGAL::to_double(pt.first.x()),
|
|
CGAL::to_double(pt.first.y()),
|
|
CGAL::to_double(pt.first.z())
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|