cgal/Polyhedron/demo/Polyhedron/Plugins/PCA/Scene_edit_box_item.cpp

1601 lines
54 KiB
C++

#include "Scene_edit_box_item.h"
#include <QApplication>
#include <CGAL/Three/Viewer_interface.h>
#include <CGAL/Qt/manipulatedFrame.h>
#include <CGAL/Qt/constraint.h>
#include <QMouseEvent>
#include <QOpenGLFramebufferObject>
#include <QOpenGLShaderProgram>
#include <QCursor>
using namespace CGAL::Three;
struct Scene_edit_box_item::vertex{
int id;
double *x;
double *y;
double *z;
CGAL::Point_3<Kernel> position()const
{
return CGAL::Point_3<Kernel>(*x,*y,*z);
}
double operator[](int i)
{
switch(i)
{
case 0:
return *x;
case 1:
return *y;
case 2:
return *z;
default:
return 0;
}
}
};
struct Scene_edit_box_item::edge{
vertex* source;
vertex* target;
};
struct Scene_edit_box_item::face{
vertex* vertices[4];
};
struct Scene_edit_box_item_priv{
typedef CGAL::Simple_cartesian<double> Kernel;
enum VAOs{
Edges = 0,
Spheres,
Faces,
S_Edges,
S_Spheres,
S_Faces,
P_Edges,
P_Spheres,
P_Faces,
NumberOfVaos
};
enum VBOs{
VertexEdges = 0,
ColorsEdges,
VertexSpheres,
NormalSpheres,
CenterSpheres,
ColorsSpheres,
VertexFaces,
NormalFaces,
ColorsFaces,
S_Vertex,
S_Normal,
NumberOfVbos
};
enum HL_Primitive{
VERTEX=0,
EDGE,
FACE,
NO_TYPE
};
Scene_edit_box_item_priv(const Scene_interface *scene_interface, Scene_edit_box_item* ebi)
{
const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
ready_to_hl = true;
scene = scene_interface;
item = ebi;
selection_on = false;
Scene_item::Bbox bb = scene->bbox();
double x=(bb.xmin()+bb.xmax())/2;
double y=(bb.ymin()+bb.ymax())/2;
double z=(bb.zmin()+bb.zmax())/2;
center_ = CGAL::qglviewer::Vec(x,y,z);
relative_center_ = CGAL::qglviewer::Vec(0,0,0);
remodel_frame = new Scene_item::ManipulatedFrame();
remodel_frame->setTranslationSensitivity(1.0);
frame = new Scene_item::ManipulatedFrame();
frame->setPosition(center_+offset);
frame->setSpinningSensitivity(100.0); //forbid spinning
constraint.setRotationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::AXIS);
constraint.setTranslationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::FREE);
constraint.setRotationConstraintDirection(CGAL::qglviewer::Vec(.0,.0,.1));
frame->setConstraint(&constraint);
//create the sphere model
pool[0] = bb.xmin(); pool[3] = bb.xmax();
pool[1] = bb.ymin(); pool[4] = bb.ymax();
pool[2] = bb.zmin(); pool[5] = bb.zmax();
vertex_spheres.resize(0);
normal_spheres.resize(0);
create_flat_sphere(1.0f, vertex_spheres, normal_spheres,10);
// 5-----6
// . | . |
// 4------7 |
// | | | |
// | 1-|---2
// | . |.
// 0------3
//vertices
for( int i = 0; i< 8; ++i)
{
vertices[i].x = ((i/2)%2==0)? &pool[0]:&pool[3];
vertices[i].y = (i/4==0)? &pool[1]:&pool[4];
vertices[i].z = (((i+1)/2)%2==1)? &pool[2]:&pool[5];
vertices[i].id = i;
}
// .--5--.
// 4 | 6 |
// .--7-1-. 2
// | | | |
// 0 .-39--.
// | 8 |10
// .--11--.
//edges
for( int i=0; i<12; ++i)
{
if(i<4)
{
edges[i].source = &vertices[i];
edges[i].target = &vertices[i+4];
}
else if(i<8)
{
edges[i].source = &vertices[i];
edges[i].target = &vertices[(i+1)%4 +4];
}
else
{
edges[i].source = &vertices[i%4];
edges[i].target = &vertices[(i+1) %4];
}
vertex_edges.resize(0);
}
//
// 5------6
// | |
// .-----. | 2 |
// . |5 . | | |
// .------.2 | 5------1------2------6------5
// | 1 | | | | | | | |
// | 4.-|-3-. | 1 | 0 | 3 | 5 |
// | . 0 |. | | | | |
// .------. 4------0------3------7------4
// | |
// | 4 |
// | |
// 4------7
//faces
for( int i=0; i<4; ++i)
{
faces[0].vertices[i] = &vertices[i];
}
for( int i=1; i<4; ++i)
{
faces[i].vertices[0] = &vertices[i];
faces[i].vertices[1] = &vertices[(i-1)];
faces[i].vertices[2] = &vertices[i+3];
faces[i].vertices[3] = &vertices[i+4];
}
faces[4].vertices[0] = &vertices[0];
faces[4].vertices[1] = &vertices[3];
faces[4].vertices[2] = &vertices[7];
faces[4].vertices[3] = &vertices[4];
for( int i=0; i<4; ++i)
{
faces[5].vertices[i] = &vertices[i+4];
}
vertex_faces.resize(0);
normal_faces.resize(0);
for(int i=0; i<8; ++i)
for(int j=0; j<3; ++j)
last_pool[i][j] = vertices[i][j];
if(QOpenGLContext::currentContext()->format().majorVersion() >= 3)
{
pick_sphere_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/cgal/Polyhedron_3/resources/shader_spheres.v");
pick_sphere_program.addShaderFromSourceFile(QOpenGLShader::Fragment,":/cgal/Polyhedron_3/resources/shader_without_light.f");
}
else
{
pick_sphere_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_spheres.v");
pick_sphere_program.addShaderFromSourceFile(QOpenGLShader::Fragment,":/cgal/Polyhedron_3/resources/compatibility_shaders/shader_without_light.f");
}
pick_sphere_program.bindAttributeLocation("colors", 1);
pick_sphere_program.link();
//Vertex source code
const char vertex_source[] =
{
"#version 430 core \n"
"in vec4 vertex; "
"in vec3 normals; "
"in vec4 colors; "
"uniform mat4 mvp_matrix; "
"uniform mat4 mv_matrix; "
"out vec4 fP; "
"out vec3 fN; "
"out vec4 color; "
"void main(void) "
"{ "
" color = colors; "
" fP = mv_matrix * vertex; "
" mat3 mv_matrix_3; "
" mv_matrix_3[0] = mv_matrix[0].xyz; "
" mv_matrix_3[1] = mv_matrix[1].xyz; "
" mv_matrix_3[2] = mv_matrix[2].xyz; "
" fN = mv_matrix_3* normals; "
" gl_Position = mvp_matrix * vertex; "
"}\n "
"\n "
};
const char vertex_source_comp[] =
{
"attribute highp vec4 vertex; "
"attribute highp vec3 normals; "
"attribute highp vec4 colors; "
"uniform highp mat4 mvp_matrix; "
"uniform highp mat4 mv_matrix; "
"varying highp vec4 fP; "
"varying highp vec3 fN; "
"varying highp vec4 color; "
"void main(void) "
"{ "
" color = colors; "
" fP = mv_matrix * vertex; "
" mat3 mv_matrix_3; "
" mv_matrix_3[0] = mv_matrix[0].xyz; "
" mv_matrix_3[1] = mv_matrix[1].xyz; "
" mv_matrix_3[2] = mv_matrix[2].xyz; "
" fN = mv_matrix_3* normals; "
" gl_Position = mvp_matrix * vertex; "
"}\n "
"\n "
};
//Fragment source code
const char fragment_source[] =
{
"#version 430 core \n"
"in vec4 color;"
"in vec4 fP; "
"in vec3 fN; "
"uniform vec4 light_pos; "
"uniform vec4 light_diff; "
"uniform vec4 light_spec; "
"uniform vec4 light_amb; "
"uniform float spec_power ; "
"uniform int is_two_side; "
"uniform bool is_selected;"
"out vec4 out_color; \n"
"void main(void) {"
" vec3 L = light_pos.xyz - fP.xyz;"
" vec3 V = -fP.xyz;"
" vec3 N;"
"if(fN == vec3(0.0,0.0,0.0)) "
"N = vec3(0.0,0.0,0.0);"
"else "
"N = normalize(fN);"
"L = normalize(L);"
"V = normalize(V);"
"vec3 R = reflect(-L, N);"
"vec4 diffuse;"
"if(is_two_side == 1) "
"diffuse = abs(dot(N,L)) * light_diff * color;"
"else "
"diffuse = max(dot(N,L), 0.0) * light_diff * color;"
"vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec;"
"vec4 ret_color = vec4((color*light_amb).xyz + diffuse.xyz + specular.xyz,1);"
"if(is_selected) "
" out_color = vec4(ret_color.r+70.0/255.0, ret_color.g+70.0/255.0, ret_color.b+70.0/255.0, color.a);"
"else "
" out_color = vec4(ret_color.rgb, color.a); }\n"
"\n"
};
//Fragment source code
const char fragment_source_comp[] =
{
"varying highp vec4 color;"
"varying highp vec4 fP; "
"varying highp vec3 fN; "
"uniform highp vec4 light_pos; "
"uniform highp vec4 light_diff; "
"uniform highp vec4 light_spec; "
"uniform highp vec4 light_amb; "
"uniform highp float spec_power ; "
"uniform int is_two_side; "
"uniform bool is_selected;"
"void main(void) {"
"highp vec3 L = light_pos.xyz - fP.xyz;"
"highp vec3 V = -fP.xyz;"
"highp vec3 N;"
"if(fN == highp vec3(0.0,0.0,0.0)) "
"N = highp vec3(0.0,0.0,0.0);"
"else "
"N = normalize(fN);"
"L = normalize(L);"
"V = normalize(V);"
"highp vec3 R = reflect(-L, N);"
"vec4 diffuse;"
"if(is_two_side == 1) "
"diffuse = abs(dot(N,L)) * light_diff * color;"
"else "
"diffuse = max(dot(N,L), 0.0) * light_diff * color;"
"highp vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec;"
"vec4 ret_color = vec4((color*light_amb).xyz + diffuse.xyz + specular.xyz,1);"
"if(is_selected) "
"gl_FragColor = vec4(ret_color.r+70.0/255.0, ret_color.g+70.0/255.0, ret_color.b+70.0/255.0, color.a);"
"else "
"gl_FragColor = vec4(ret_color.rgb, color.a); }\n"
"\n"
};
if(QOpenGLContext::currentContext()->format().majorVersion() >= 3)
{
transparent_face_program.addShaderFromSourceCode(QOpenGLShader::Vertex,vertex_source);
transparent_face_program.addShaderFromSourceCode(QOpenGLShader::Fragment,fragment_source);
}
else
{
transparent_face_program.addShaderFromSourceCode(QOpenGLShader::Vertex,vertex_source_comp);
transparent_face_program.addShaderFromSourceCode(QOpenGLShader::Fragment,fragment_source_comp);
}
transparent_face_program.bindAttributeLocation("colors", 1);
transparent_face_program.link();
reset_selection();
last_picked_id = -1;
last_picked_type = -1;
QPixmap pix(":/cgal/cursors/resources/rotate_around_cursor.png");
rotate_cursor = QCursor(pix);
}
~Scene_edit_box_item_priv(){
delete frame;
delete remodel_frame;
}
mutable std::vector<float> vertex_edges;
mutable std::vector<float> color_edges;
mutable std::vector<float> vertex_spheres;
mutable std::vector<float> normal_spheres;
mutable std::vector<float> center_spheres;
mutable std::vector<float> color_spheres;
mutable std::vector<float> vertex_faces;
mutable std::vector<float> normal_faces;
mutable std::vector<float> color_faces;
mutable std::vector<float> hl_vertex;
mutable std::vector<float> hl_normal;
double pool[6];
//id|coord
double last_pool[8][3];
bool ready_to_hl;
CGAL::qglviewer::ManipulatedFrame* frame;
CGAL::qglviewer::ManipulatedFrame* remodel_frame;
CGAL::qglviewer::Vec rf_last_pos;
CGAL::qglviewer::LocalConstraint constraint;
CGAL::qglviewer::Vec center_;
CGAL::qglviewer::Vec relative_center_;
mutable QOpenGLShaderProgram pick_sphere_program;
mutable QOpenGLShaderProgram transparent_face_program;
mutable Scene_edit_box_item::vertex vertices[8];
mutable Scene_edit_box_item::edge edges[12];
mutable Scene_edit_box_item::face faces[6];
std::vector<Scene_edit_box_item::vertex*> selected_vertices;
void reset_selection();
bool selection_on;
void picking(int& type, int& id, Viewer_interface *viewer);
mutable QOpenGLShaderProgram* program;
void initializeBuffers(Viewer_interface *viewer)const;
void computeElements() const;
void draw_picking(Viewer_interface*);
void remodel_box(const QVector3D &dir);
double applyX(int id, double x, double dirx);
double applyY(int id, double y, double diry);
double applyZ(int id, double z, double dirz);
const Scene_interface* scene;
Scene_edit_box_item* item;
QPoint picked_pixel;
HL_Primitive hl_type;
int last_picked_id;
int last_picked_type;
QCursor rotate_cursor;
};
Scene_edit_box_item::Scene_edit_box_item()
{
d = NULL;
}
Scene_edit_box_item::Scene_edit_box_item(const Scene_interface *scene_interface)
: Scene_item(Scene_edit_box_item_priv::NumberOfVbos,Scene_edit_box_item_priv::NumberOfVaos)
{
d = new Scene_edit_box_item_priv(scene_interface, this);
are_buffers_filled = false;
CGAL::QGLViewer* viewer = *CGAL::QGLViewer::QGLViewerPool().begin();
viewer->setMouseTracking(true);
}
QString Scene_edit_box_item::toolTip() const {
return QString();
}
void Scene_edit_box_item::drawSpheres(Viewer_interface *viewer, const QMatrix4x4 f_matrix ) const
{
vaos[Scene_edit_box_item_priv::Spheres]->bind();
GLdouble d_mat[16];
QMatrix4x4 mvp_mat;
viewer->camera()->getModelViewProjectionMatrix(d_mat);
for (int i=0; i<16; ++i)
mvp_mat.data()[i] = GLfloat(d_mat[i]);
mvp_mat = mvp_mat*f_matrix;
QMatrix4x4 mv_mat;
viewer->camera()->getModelViewMatrix(d_mat);
for (int i=0; i<16; ++i)
mv_mat.data()[i] = GLfloat(d_mat[i]);
mv_mat = mv_mat*f_matrix;
QVector4D light_pos(0.0f,0.0f,1.0f, 1.0f );
light_pos = light_pos*f_matrix;
double radius =std::sqrt(
(point(6,0) - point(0,0)) * (point(6,0) - point(0,0)) +
(point(6,1) - point(0,1)) * (point(6,1) - point(0,1)) +
(point(6,2) - point(0,2)) * (point(6,2) - point(0,2))) *0.02 ;
attribBuffers(viewer, PROGRAM_SPHERES);
d->program = getShaderProgram(PROGRAM_SPHERES, viewer);
d->program->bind();
d->program->setUniformValue("mvp_matrix", mvp_mat);
d->program->setUniformValue("mv_matrix", mv_mat);
d->program->setUniformValue("light_pos", light_pos);
d->program->setUniformValue("is_clipbox_on", false);
d->program->setAttributeValue("radius",radius);
d->program->setAttributeValue("colors", QColor(Qt::red));
viewer->glDrawArraysInstanced(GL_TRIANGLES, 0,
static_cast<GLsizei>(d->vertex_spheres.size()/3),
static_cast<GLsizei>(8));
d->program->release();
vaos[Scene_edit_box_item_priv::Spheres]->release();
}
void Scene_edit_box_item::draw(Viewer_interface *viewer) const
{
if (!are_buffers_filled)
{
d->computeElements();
d->initializeBuffers(viewer);
}
QMatrix4x4 f_matrix;
for (int i=0; i<16; ++i){
f_matrix.data()[i] = (float)d->frame->matrix()[i];
}
drawSpheres(viewer, f_matrix);
}
void Scene_edit_box_item::drawEdges(Viewer_interface* viewer) const
{
if(!are_buffers_filled)
{
d->computeElements();
d->initializeBuffers(viewer);
}
QMatrix4x4 f_matrix;
for (int i=0; i<16; ++i){
f_matrix.data()[i] = (float)d->frame->matrix()[i];
}
vaos[Scene_edit_box_item_priv::Edges]->bind();
if(!viewer->isOpenGL_4_3())
{
attribBuffers(viewer, PROGRAM_WITHOUT_LIGHT);
d->program = getShaderProgram(PROGRAM_WITHOUT_LIGHT);
d->program->bind();
d->program->setUniformValue("is_clipbox_on", false);
}
else
{
attribBuffers(viewer, PROGRAM_SOLID_WIREFRAME);
d->program = getShaderProgram(PROGRAM_SOLID_WIREFRAME);
d->program->bind();
QVector2D vp(viewer->width(), viewer->height());
d->program->setUniformValue("viewport", vp);
d->program->setUniformValue("near",(GLfloat)viewer->camera()->zNear());
d->program->setUniformValue("far",(GLfloat)viewer->camera()->zFar());
d->program->setUniformValue("width", 6.0f);
}
d->program->setUniformValue("f_matrix", f_matrix);
d->program->setAttributeValue("colors", QColor(Qt::black));
viewer->glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(d->vertex_edges.size()/3));
vaos[Scene_edit_box_item_priv::Edges]->release();
d->program->release();
if(renderingMode() == Wireframe)
{
drawSpheres(viewer, f_matrix);
}
drawHl(viewer);
drawTransparent(viewer);
}
void Scene_edit_box_item::compute_bbox() const
{
const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
QVector3D min(d->pool[0], d->pool[1], d->pool[2]);
QVector3D max(d->pool[3], d->pool[4], d->pool[5]);
for(int i=0; i< 3; ++i)
{
min[i] += d->frame->translation()[i]-d->center_[i]-offset[i];
max[i] += d->frame->translation()[i]-d->center_[i]-offset[i];
}
_bbox = Scene_item::Bbox(min.x(),min.y(),min.z(),max.x(),max.y(),max.z());
}
void
Scene_edit_box_item_priv::initializeBuffers(Viewer_interface *viewer)const
{
//vao containing the data for the lines
{
if(viewer->isOpenGL_4_3())
program = item->getShaderProgram(Scene_edit_box_item::PROGRAM_SOLID_WIREFRAME, viewer);
else
program = item->getShaderProgram(Scene_edit_box_item::PROGRAM_WITHOUT_LIGHT, viewer);
program->bind();
item->vaos[Edges]->bind();
item->buffers[VertexEdges].bind();
item->buffers[VertexEdges].allocate(vertex_edges.data(),
static_cast<GLsizei>(vertex_edges.size()*sizeof(float)));
program->enableAttributeArray("vertex");
program->setAttributeBuffer("vertex",GL_FLOAT,0,3);
item->buffers[VertexEdges].release();
item->vaos[Edges]->release();
item->vaos[P_Edges]->bind();
item->buffers[VertexEdges].bind();
program->enableAttributeArray("vertex");
program->setAttributeBuffer("vertex",GL_FLOAT,0,3);
item->buffers[VertexEdges].release();
item->buffers[ColorsEdges].bind();
item->buffers[ColorsEdges].allocate(color_edges.data(),
static_cast<GLsizei>(color_edges.size()*sizeof(float)));
program->enableAttributeArray("colors");
program->setAttributeBuffer("colors",GL_FLOAT,0,3);
item->buffers[ColorsEdges].release();
item->vaos[P_Edges]->release();
program->release();
}
//vao containing the data for the spheres
{
program = item->getShaderProgram(Scene_edit_box_item::PROGRAM_SPHERES, viewer);
item->attribBuffers(viewer, Scene_edit_box_item::PROGRAM_SPHERES);
program->bind();
item->vaos[Spheres]->bind();
item->buffers[VertexSpheres].bind();
item->buffers[VertexSpheres].allocate(vertex_spheres.data(),
static_cast<int>(vertex_spheres.size()*sizeof(float)));
program->enableAttributeArray("vertex");
program->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
item->buffers[VertexSpheres].release();
item->buffers[NormalSpheres].bind();
item->buffers[NormalSpheres].allocate(normal_spheres.data(),
static_cast<int>(normal_spheres.size()*sizeof(float)));
program->enableAttributeArray("normals");
program->setAttributeBuffer("normals", GL_FLOAT, 0, 3);
item->buffers[NormalSpheres].release();
item->buffers[CenterSpheres].bind();
item->buffers[CenterSpheres].allocate(center_spheres.data(),
static_cast<int>(center_spheres.size()*sizeof(float)));
program->enableAttributeArray("center");
program->setAttributeBuffer("center", GL_FLOAT, 0, 3);
item->buffers[CenterSpheres].release();
program->disableAttributeArray("radius");
program->disableAttributeArray("colors");
viewer->glVertexAttribDivisor(program->attributeLocation("center"), 1);
viewer->glVertexAttribDivisor(program->attributeLocation("radius"), 1);
item->vaos[Spheres]->release();
program->release();
pick_sphere_program.bind();
pick_sphere_program.bind();
item->vaos[P_Spheres]->bind();
item->buffers[VertexSpheres].bind();
pick_sphere_program.enableAttributeArray("vertex");
pick_sphere_program.setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
item->buffers[VertexSpheres].release();
item->buffers[NormalSpheres].bind();
pick_sphere_program.disableAttributeArray("normals");
pick_sphere_program.setAttributeValue("normals",QVector3D(0,0,0));
item->buffers[NormalSpheres].release();
item->buffers[CenterSpheres].bind();
pick_sphere_program.enableAttributeArray("center");
pick_sphere_program.setAttributeBuffer("center", GL_FLOAT, 0, 3);
item->buffers[CenterSpheres].release();
pick_sphere_program.disableAttributeArray("radius");
viewer->glVertexAttribDivisor(program->attributeLocation("radius"), 1);
item->buffers[ColorsSpheres].bind();
item->buffers[ColorsSpheres].allocate(color_spheres.data(),
static_cast<int>(color_spheres.size()*sizeof(float)));
pick_sphere_program.enableAttributeArray("colors");
pick_sphere_program.setAttributeBuffer("colors", GL_FLOAT, 0, 3);
item->buffers[ColorsSpheres].release();
viewer->glVertexAttribDivisor(program->attributeLocation("center"), 1);
viewer->glVertexAttribDivisor(program->attributeLocation("colors"), 1);
item->vaos[P_Spheres]->release();
pick_sphere_program.release();
}
//vao containing the data for the faces
{
program = item->getShaderProgram(Scene_edit_box_item::PROGRAM_WITH_LIGHT, viewer);
item->attribBuffers(viewer, Scene_edit_box_item::PROGRAM_WITH_LIGHT);
program->bind();
item->vaos[Faces]->bind();
item->buffers[VertexFaces].bind();
item->buffers[VertexFaces].allocate(vertex_faces.data(),
static_cast<int>(vertex_faces.size()*sizeof(float)));
program->enableAttributeArray("vertex");
program->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
item->buffers[VertexFaces].release();
item->buffers[NormalFaces].bind();
item->buffers[NormalFaces].allocate(normal_faces.data(),
static_cast<int>(normal_faces.size()*sizeof(float)));
program->enableAttributeArray("normals");
program->setAttributeBuffer("normals", GL_FLOAT, 0, 3);
item->buffers[NormalFaces].release();
item->vaos[Faces]->release();
program->release();
program = item->getShaderProgram(Scene_edit_box_item::PROGRAM_WITHOUT_LIGHT, viewer);
item->attribBuffers(viewer, Scene_edit_box_item::PROGRAM_WITHOUT_LIGHT);
program->bind();
item->vaos[P_Faces]->bind();
item->buffers[VertexFaces].bind();
program->enableAttributeArray("vertex");
program->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
item->buffers[VertexFaces].release();
item->buffers[ColorsFaces].bind();
item->buffers[ColorsFaces].allocate(color_faces.data(),
static_cast<int>(color_faces.size()*sizeof(float)));
program->enableAttributeArray("colors");
program->setAttributeBuffer("colors", GL_FLOAT, 0, 3);
item->buffers[ColorsFaces].release();
item->vaos[P_Faces]->release();
program->release();
}
item->are_buffers_filled = true;
}
void push_xyz(std::vector<float> &v,
const Scene_edit_box_item::Kernel::Point_3& p,
CGAL::qglviewer::Vec center_ = CGAL::qglviewer::Vec(0,0,0))
{
v.push_back(p.x()-center_.x);
v.push_back(p.y()-center_.y);
v.push_back(p.z()-center_.z);
}
void push_normal(std::vector<float> &v, int id)
{
switch(id)
{
case 0:
v.push_back(0);
v.push_back(-1);
v.push_back(0);
break;
case 1:
v.push_back(-1);
v.push_back(0);
v.push_back(0);
break;
case 2:
v.push_back(0);
v.push_back(0);
v.push_back(-1);
break;
case 3:
v.push_back(1);
v.push_back(0);
v.push_back(0);
break;
case 4:
v.push_back(0);
v.push_back(0);
v.push_back(1);
break;
case 5:
v.push_back(0);
v.push_back(1);
v.push_back(0);
break;
default:
break;
}
}
void Scene_edit_box_item_priv::computeElements() const
{
vertex_edges.clear();
vertex_faces.clear();
normal_faces.clear();
center_spheres.clear();
color_edges.clear();
color_faces.clear();
color_spheres.clear();
//edges
for( int i=0; i<12; ++i)
{
if(i<4)
{
vertex_edges.push_back(vertices[i].position().x()-center_.x);
vertex_edges.push_back(vertices[i].position().y()-center_.y);
vertex_edges.push_back(vertices[i].position().z()-center_.z);
center_spheres.push_back(vertices[i].position().x()-center_.x);
center_spheres.push_back(vertices[i].position().y()-center_.y);
center_spheres.push_back(vertices[i].position().z()-center_.z);
vertex_edges.push_back(vertices[i+4].position().x()-center_.x);
vertex_edges.push_back(vertices[i+4].position().y()-center_.y);
vertex_edges.push_back(vertices[i+4].position().z()-center_.z);
}
else if(i<8)
{
vertex_edges.push_back(vertices[i].position().x()-center_.x);
vertex_edges.push_back(vertices[i].position().y()-center_.y);
vertex_edges.push_back(vertices[i].position().z()-center_.z);
center_spheres.push_back(vertices[i].position().x()-center_.x);
center_spheres.push_back(vertices[i].position().y()-center_.y);
center_spheres.push_back(vertices[i].position().z()-center_.z);
vertex_edges.push_back(vertices[(i+1)%4 +4].position().x()-center_.x);
vertex_edges.push_back(vertices[(i+1)%4 +4].position().y()-center_.y);
vertex_edges.push_back(vertices[(i+1)%4 +4].position().z()-center_.z);
}
else
{
vertex_edges.push_back(vertices[i%4].position().x()-center_.x);
vertex_edges.push_back(vertices[i%4].position().y()-center_.y);
vertex_edges.push_back(vertices[i%4].position().z()-center_.z);
vertex_edges.push_back(vertices[(i+1) %4].position().x()-center_.x);
vertex_edges.push_back(vertices[(i+1) %4].position().y()-center_.y);
vertex_edges.push_back(vertices[(i+1) %4].position().z()-center_.z);
}
color_edges.push_back(0);
color_edges.push_back((20.0*i+10)/255);
color_edges.push_back(0);
color_edges.push_back(0);
color_edges.push_back((20.0*i+10)/255);
color_edges.push_back(0);
}
//faces
for( int i=0; i<6; ++i)
{
push_xyz(vertex_faces, faces[i].vertices[0]->position(), center_);
push_xyz(vertex_faces, faces[i].vertices[3]->position(), center_);
push_xyz(vertex_faces, faces[i].vertices[2]->position(), center_);
push_xyz(vertex_faces, faces[i].vertices[0]->position(), center_);
push_xyz(vertex_faces, faces[i].vertices[2]->position(), center_);
push_xyz(vertex_faces, faces[i].vertices[1]->position(), center_);
for( int j=0; j<6; ++j)
{
push_normal(normal_faces, i);
color_faces.push_back(0);
color_faces.push_back(0);
color_faces.push_back((20.0*i+10)/255);
}
}
//spheres
for( int i=0; i<8; ++i)
{
color_spheres.push_back((20.0*i+10)/255);
color_spheres.push_back(0);
color_spheres.push_back(0);
}
}
Scene_edit_box_item::~Scene_edit_box_item()
{
CGAL::QGLViewer* viewer = *CGAL::QGLViewer::QGLViewerPool().begin();
viewer->setMouseTracking(false);
delete d;
}
// Indicate if rendering mode is supported
bool Scene_edit_box_item::supportsRenderingMode(RenderingMode m) const {
return (m==Wireframe || m==FlatPlusEdges);
}
Scene_item::ManipulatedFrame*
Scene_edit_box_item::manipulatedFrame()
{
return d->frame;
}
double Scene_edit_box_item::point(short i, short j) const
{
CGAL::qglviewer::Vec pos(d->vertices[i].position().x()-d->center_.x,
d->vertices[i].position().y()-d->center_.y,
d->vertices[i].position().z()-d->center_.z);
return (d->frame->inverseCoordinatesOf(pos))[j];
}
void Scene_edit_box_item::highlight(Viewer_interface *viewer)
{
d->ready_to_hl = true;
viewer->makeCurrent();
int type = -1, id = -1;
//pick
if(!d->selection_on)
{
d->picking(type, id, viewer);
d->last_picked_id = id;
d->last_picked_type = type;
}
//highlight
d->hl_normal.clear();
d->hl_vertex.clear();
if(type !=-1)
{
switch(d->last_picked_type)
{
case 0:
{
//compute
d->hl_vertex.push_back(d->vertices[d->last_picked_id].position().x()-d->center_.x);
d->hl_vertex.push_back(d->vertices[d->last_picked_id].position().y()-d->center_.y);
d->hl_vertex.push_back(d->vertices[d->last_picked_id].position().z()-d->center_.z);
//fill buffers
d->program = getShaderProgram(Scene_edit_box_item::PROGRAM_SPHERES, viewer);
d->program->bind();
vaos[Scene_edit_box_item_priv::S_Spheres]->bind();
buffers[Scene_edit_box_item_priv::VertexSpheres].bind();
buffers[Scene_edit_box_item_priv::VertexSpheres].allocate(d->vertex_spheres.data(),
static_cast<int>(d->vertex_spheres.size()*sizeof(float)));
d->program->enableAttributeArray("vertex");
d->program->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
buffers[Scene_edit_box_item_priv::VertexSpheres].release();
buffers[Scene_edit_box_item_priv::NormalSpheres].bind();
buffers[Scene_edit_box_item_priv::NormalSpheres].allocate(d->normal_spheres.data(),
static_cast<int>(d->normal_spheres.size()*sizeof(float)));
d->program->enableAttributeArray("normals");
d->program->setAttributeBuffer("normals", GL_FLOAT, 0, 3);
buffers[Scene_edit_box_item_priv::NormalSpheres].release();
buffers[Scene_edit_box_item_priv::S_Vertex].bind();
buffers[Scene_edit_box_item_priv::S_Vertex].allocate(d->hl_vertex.data(),
static_cast<int>(d->hl_vertex.size()*sizeof(float)));
d->program->enableAttributeArray("center");
d->program->setAttributeBuffer("center", GL_FLOAT, 0, 3);
buffers[Scene_edit_box_item_priv::S_Vertex].release();
d->program->disableAttributeArray("colors");
viewer->glVertexAttribDivisor(d->program->attributeLocation("center"), 1);
d->program->release();
vaos[Scene_edit_box_item_priv::S_Spheres]->release();
//draw
d->hl_type = Scene_edit_box_item_priv::VERTEX;
break;
}
case 1:
{
//compute
d->hl_vertex.push_back(d->edges[d->last_picked_id].source->position().x()-d->center_.x);
d->hl_vertex.push_back(d->edges[d->last_picked_id].source->position().y()-d->center_.y);
d->hl_vertex.push_back(d->edges[d->last_picked_id].source->position().z()-d->center_.z);
d->hl_vertex.push_back(d->edges[d->last_picked_id].target->position().x()-d->center_.x);
d->hl_vertex.push_back(d->edges[d->last_picked_id].target->position().y()-d->center_.y);
d->hl_vertex.push_back(d->edges[d->last_picked_id].target->position().z()-d->center_.z);
//fill buffers
d->program = viewer->isOpenGL_4_3()
? getShaderProgram(Scene_edit_box_item::PROGRAM_SOLID_WIREFRAME, viewer)
: getShaderProgram(Scene_edit_box_item::PROGRAM_WITHOUT_LIGHT, viewer);
d->program->bind();
vaos[Scene_edit_box_item_priv::S_Edges]->bind();
buffers[Scene_edit_box_item_priv::S_Vertex].bind();
buffers[Scene_edit_box_item_priv::S_Vertex].allocate(d->hl_vertex.data(),
static_cast<GLsizei>(d->hl_vertex.size()*sizeof(float)));
d->program->enableAttributeArray("vertex");
d->program->setAttributeBuffer("vertex",GL_FLOAT,0,3);
buffers[Scene_edit_box_item_priv::S_Vertex].release();
vaos[Scene_edit_box_item_priv::S_Edges]->release();
d->program->release();
//draw
d->hl_type = Scene_edit_box_item_priv::EDGE;
break;
}
case 2:
{
//compute
push_xyz(d->hl_vertex, d->faces[d->last_picked_id].vertices[0]->position(), d->center_);
push_xyz(d->hl_vertex, d->faces[d->last_picked_id].vertices[3]->position(), d->center_);
push_xyz(d->hl_vertex, d->faces[d->last_picked_id].vertices[2]->position(), d->center_);
push_xyz(d->hl_vertex, d->faces[d->last_picked_id].vertices[0]->position(), d->center_);
push_xyz(d->hl_vertex, d->faces[d->last_picked_id].vertices[2]->position(), d->center_);
push_xyz(d->hl_vertex, d->faces[d->last_picked_id].vertices[1]->position(), d->center_);
for( int j=0; j<6; ++j)
{
push_normal(d->hl_normal, d->last_picked_id);
}
//fill buffers
d->program = getShaderProgram(Scene_edit_box_item::PROGRAM_WITH_LIGHT, viewer);
attribBuffers(viewer, Scene_edit_box_item::PROGRAM_WITH_LIGHT);
d->program->bind();
vaos[Scene_edit_box_item_priv::S_Faces]->bind();
buffers[Scene_edit_box_item_priv::S_Vertex].bind();
buffers[Scene_edit_box_item_priv::S_Vertex].allocate(d->hl_vertex.data(),
static_cast<int>(d->hl_vertex.size()*sizeof(float)));
d->program->enableAttributeArray("vertex");
d->program->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
buffers[Scene_edit_box_item_priv::S_Normal].release();
buffers[Scene_edit_box_item_priv::S_Normal].bind();
buffers[Scene_edit_box_item_priv::S_Normal].allocate(d->hl_normal.data(),
static_cast<int>(d->hl_normal.size()*sizeof(float)));
d->program->enableAttributeArray("normals");
d->program->setAttributeBuffer("normals", GL_FLOAT, 0, 3);
buffers[Scene_edit_box_item_priv::S_Normal].release();
vaos[Scene_edit_box_item_priv::S_Faces]->release();
d->program->release();
//draw
d->hl_type = Scene_edit_box_item_priv::FACE;
break;
}
default:
d->hl_type = Scene_edit_box_item_priv::NO_TYPE;
break;
}
}
itemChanged();
d->ready_to_hl = false;
}
void Scene_edit_box_item::clearHL()
{
Viewer_interface* viewer = dynamic_cast<Viewer_interface*>(*CGAL::QGLViewer::QGLViewerPool().begin());
viewer->makeCurrent();
d->hl_normal.clear();
d->hl_vertex.clear();
d->program = getShaderProgram(Scene_edit_box_item::PROGRAM_SPHERES, viewer);
d->program->bind();
vaos[Scene_edit_box_item_priv::S_Spheres]->bind();
buffers[Scene_edit_box_item_priv::VertexSpheres].bind();
buffers[Scene_edit_box_item_priv::VertexSpheres].allocate(d->vertex_spheres.data(),
static_cast<int>(d->vertex_spheres.size()*sizeof(float)));
d->program->enableAttributeArray("vertex");
d->program->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
buffers[Scene_edit_box_item_priv::VertexSpheres].release();
buffers[Scene_edit_box_item_priv::NormalSpheres].bind();
buffers[Scene_edit_box_item_priv::NormalSpheres].allocate(d->normal_spheres.data(),
static_cast<int>(d->normal_spheres.size()*sizeof(float)));
d->program->enableAttributeArray("normals");
d->program->setAttributeBuffer("normals", GL_FLOAT, 0, 3);
buffers[Scene_edit_box_item_priv::NormalSpheres].release();
buffers[Scene_edit_box_item_priv::S_Vertex].bind();
buffers[Scene_edit_box_item_priv::S_Vertex].allocate(d->hl_vertex.data(),
static_cast<int>(d->hl_vertex.size()*sizeof(float)));
d->program->enableAttributeArray("center");
d->program->setAttributeBuffer("center", GL_FLOAT, 0, 3);
buffers[Scene_edit_box_item_priv::S_Vertex].release();
d->program->disableAttributeArray("colors");
viewer->glVertexAttribDivisor(d->program->attributeLocation("center"), 1);
d->program->release();
vaos[Scene_edit_box_item_priv::S_Spheres]->release();
//draw
d->hl_type = Scene_edit_box_item_priv::VERTEX;
d->program = getShaderProgram(Scene_edit_box_item::PROGRAM_WITHOUT_LIGHT, viewer);
d->program->bind();
vaos[Scene_edit_box_item_priv::S_Edges]->bind();
buffers[Scene_edit_box_item_priv::S_Vertex].bind();
buffers[Scene_edit_box_item_priv::S_Vertex].allocate(d->hl_vertex.data(),
static_cast<GLsizei>(d->hl_vertex.size()*sizeof(float)));
d->program->enableAttributeArray("vertex");
d->program->setAttributeBuffer("vertex",GL_FLOAT,0,3);
buffers[Scene_edit_box_item_priv::S_Vertex].release();
vaos[Scene_edit_box_item_priv::S_Edges]->release();
d->program->release();
d->program = getShaderProgram(Scene_edit_box_item::PROGRAM_WITH_LIGHT, viewer);
attribBuffers(viewer, Scene_edit_box_item::PROGRAM_WITH_LIGHT);
d->program->bind();
vaos[Scene_edit_box_item_priv::S_Faces]->bind();
buffers[Scene_edit_box_item_priv::S_Vertex].bind();
buffers[Scene_edit_box_item_priv::S_Vertex].allocate(d->hl_vertex.data(),
static_cast<int>(d->hl_vertex.size()*sizeof(float)));
d->program->enableAttributeArray("vertex");
d->program->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
buffers[Scene_edit_box_item_priv::S_Normal].release();
buffers[Scene_edit_box_item_priv::S_Normal].bind();
buffers[Scene_edit_box_item_priv::S_Normal].allocate(d->hl_normal.data(),
static_cast<int>(d->hl_normal.size()*sizeof(float)));
d->program->enableAttributeArray("normals");
d->program->setAttributeBuffer("normals", GL_FLOAT, 0, 3);
buffers[Scene_edit_box_item_priv::S_Normal].release();
vaos[Scene_edit_box_item_priv::S_Faces]->release();
d->program->release();
d->hl_type = Scene_edit_box_item_priv::NO_TYPE;
itemChanged();
}
void Scene_edit_box_item_priv::reset_selection()
{
selection_on = false;
CGAL::QGLViewer* viewer = *CGAL::QGLViewer::QGLViewerPool().begin();
viewer->setManipulatedFrame(frame);
viewer->setMouseBinding(Qt::ShiftModifier, Qt::LeftButton, CGAL::qglviewer::SELECT);
constraint.setTranslationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::FREE);
selected_vertices.clear();
}
//intercept events for picking
bool Scene_edit_box_item::eventFilter(QObject *obj, QEvent *event)
{
if(!visible())
return false;
CGAL::Three::Viewer_interface* viewer = qobject_cast<CGAL::Three::Viewer_interface*>(obj);
if(!viewer)
return false;
if(event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* e = static_cast<QMouseEvent*>(event);
if(e->modifiers() == Qt::NoModifier)
{
Viewer_interface* v_i = dynamic_cast<Viewer_interface*>(viewer);
//pick
int type, picked;
d->picked_pixel = e->pos();
d->picking(type, picked, v_i);
if(type !=-1)
{
bool found = false;
QApplication::setOverrideCursor(Qt::DragMoveCursor);
CGAL::qglviewer::Vec pos = viewer->camera()->pointUnderPixel(d->picked_pixel, found);
if(found)
{
d->rf_last_pos = pos;
d->remodel_frame->setPosition(pos);
}
for(int i=0; i<8; ++i)
for(int j=0; j<3; ++j)
d->last_pool[i][j] = d->vertices[i][j];
d->selection_on = true;
if(type == 0)
{
d->selected_vertices.push_back(&d->vertices[picked]);
d->constraint.setTranslationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::FREE);
d->remodel_frame->setConstraint(&d->constraint);
}
else if(type == 1)
{
d->selected_vertices.push_back(d->edges[picked].source);
d->selected_vertices.push_back(d->edges[picked].target);
Kernel::Point_3 s(d->edges[picked].source->position()), t(d->edges[picked].target->position());
CGAL::qglviewer::Vec normal(t.x()-s.x(), t.y()-s.y(), t.z()-s.z());
d->constraint.setTranslationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::PLANE);
d->constraint.setTranslationConstraintDirection(normal);
d->remodel_frame->setConstraint(&d->constraint);
}
else if(type == 2)
{
for(int i=0; i<4; ++i)
d->selected_vertices.push_back(d->faces[picked].vertices[i]);
Kernel::Point_3 a1(d->faces[picked].vertices[1]->position()), a0(d->faces[picked].vertices[0]->position())
,a3(d->faces[picked].vertices[3]->position());
QVector3D a(a1.x()-a0.x(), a1.y()-a0.y(),a1.z()-a0.z()),b(a3.x()-a0.x(), a3.y()-a0.y(),a3.z()-a0.z());
QVector3D n = QVector3D::crossProduct(a,b);
d->remodel_frame->setConstraint(&d->constraint);
d->constraint.setTranslationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::AXIS);
d->constraint.setTranslationConstraintDirection(CGAL::qglviewer::Vec(n.x(), n.y(), n.z()));
}
viewer->setManipulatedFrame(d->remodel_frame);
viewer->setMouseBinding(
Qt::NoModifier,
Qt::LeftButton,
CGAL::qglviewer::FRAME,
CGAL::qglviewer::TRANSLATE);
}
else
{
d->reset_selection();
}
}
return false;
}
else if(event->type() == QEvent::MouseMove)
{
QMouseEvent* e = static_cast<QMouseEvent*>(event);
if(e->modifiers() == Qt::NoModifier)
{
if(d->selection_on)
{
d->remodel_frame->setOrientation(d->frame->orientation());
CGAL::qglviewer::Vec td(d->remodel_frame->transformOf(d->remodel_frame->position() - d->rf_last_pos));
QVector3D dir(td.x, td.y, td.z);
d->remodel_box(dir);
}
d->ready_to_hl= true;
d->picked_pixel = e->pos();
QTimer::singleShot(0, this,
[this, viewer](){
highlight(viewer);
});
}
else if(e->modifiers() == Qt::ControlModifier &&
e->buttons() == Qt::LeftButton)
{
QApplication::setOverrideCursor(d->rotate_cursor);
}
else if(d->selection_on)
{
d->reset_selection();
}
d->picked_pixel = e->pos();
return false;
}
else if(event->type() == QEvent::MouseButtonRelease)
{
d->reset_selection();
QApplication::setOverrideCursor(QCursor());
viewer->setMouseBinding(
Qt::NoModifier,
Qt::LeftButton,
CGAL::qglviewer::CAMERA,
CGAL::qglviewer::ROTATE);
}
else if(event->type() == QEvent::KeyRelease)
{
QKeyEvent* e = static_cast<QKeyEvent*>(event);
if(e->key() == Qt::Key_Control)
{
QApplication::setOverrideCursor(QCursor());
}
}
return false;
}
void Scene_edit_box_item_priv::draw_picking(Viewer_interface* viewer)
{
QMatrix4x4 f_matrix;
for (int i=0; i<16; ++i){
f_matrix.data()[i] = (float)frame->matrix()[i];
}
GLdouble d_mat[16];
QMatrix4x4 mvp_mat;
viewer->camera()->getModelViewProjectionMatrix(d_mat);
for (int i=0; i<16; ++i)
mvp_mat.data()[i] = GLfloat(d_mat[i]);
mvp_mat = mvp_mat*f_matrix;
QMatrix4x4 mv_mat;
viewer->camera()->getModelViewMatrix(d_mat);
for (int i=0; i<16; ++i)
mv_mat.data()[i] = GLfloat(d_mat[i]);
mv_mat = mv_mat*f_matrix;
QVector4D light_pos(0.0f,0.0f,1.0f, 1.0f );
light_pos = light_pos*f_matrix;
if(item->renderingMode() == FlatPlusEdges)
{
item->vaos[P_Faces]->bind();
program = item->getShaderProgram(Scene_item::PROGRAM_WITHOUT_LIGHT, viewer);
item->attribBuffers(viewer, Scene_item::PROGRAM_WITHOUT_LIGHT);
program->bind();
program->setUniformValue("mvp_matrix", mvp_mat);
program->setUniformValue("is_clipbox_on", false);
viewer->glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(vertex_faces.size()/3));
item->vaos[P_Faces]->release();
program->release();
}
item->vaos[P_Spheres]->bind();
pick_sphere_program.bind();
pick_sphere_program.setUniformValue("mvp_matrix", mvp_mat);
pick_sphere_program.setUniformValue("is_clipbox_on", GLboolean(false));
viewer->glDrawArraysInstanced(GL_TRIANGLES, 0,
static_cast<GLsizei>(vertex_spheres.size()/3),
static_cast<GLsizei>(8));
pick_sphere_program.release();
item->vaos[P_Spheres]->release();
item->vaos[P_Edges]->bind();
if(!viewer->isOpenGL_4_3())
{
item->attribBuffers(viewer, Scene_item::PROGRAM_WITHOUT_LIGHT);
program = item->getShaderProgram(Scene_item::PROGRAM_WITHOUT_LIGHT);
program->bind();
program->setUniformValue("is_clipbox_on", false);
}
else
{
item->attribBuffers(viewer, Scene_item::PROGRAM_SOLID_WIREFRAME);
program = item->getShaderProgram(Scene_item::PROGRAM_SOLID_WIREFRAME);
program->bind();
QVector2D vp(viewer->width(), viewer->height());
program->setUniformValue("viewport", vp);
program->setUniformValue("near",(GLfloat)viewer->camera()->zNear());
program->setUniformValue("far",(GLfloat)viewer->camera()->zFar());
program->setUniformValue("width", 6.0f);
}
program->setUniformValue("f_matrix", f_matrix);
viewer->glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(vertex_edges.size()/3));
item->vaos[P_Edges]->release();
program->release();
}
void Scene_edit_box_item_priv::remodel_box(const QVector3D &dir)
{
CGAL::qglviewer::AxisPlaneConstraint::Type prev_cons = constraint.translationConstraintType();
constraint.setTranslationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::FREE);
Q_FOREACH(Scene_edit_box_item::vertex* selected_vertex, selected_vertices )
{
int id = selected_vertex->id;
*selected_vertex->x = applyX(id, last_pool[id][0], dir.x());
*selected_vertex->y = applyY(id, last_pool[id][1], dir.y());
*selected_vertex->z = applyZ(id, last_pool[id][2], dir.z());
for( int i=0; i<3; ++i)
relative_center_[i] =(pool[i]+pool[i+3])/2 - center_[i];
for( int i=0; i<3; ++i)
center_[i] =(pool[i]+pool[i+3])/2;
frame->translate(frame->inverseTransformOf(relative_center_));
}
item->invalidateOpenGLBuffers();
constraint.setTranslationConstraintType(prev_cons);
}
double Scene_edit_box_item_priv::applyX(int id, double x, double dirx)
{
switch(id)
{
case 0:
case 1:
case 4:
case 5:
if(x+dirx < pool[3])
return x+dirx;
else
return pool[3];
case 2:
case 3:
case 6:
case 7:
if(x+dirx > pool[0])
return x+dirx;
else
return pool[0];
default:
return 0;
}
return 0;
}
double Scene_edit_box_item_priv::applyY(int id, double y, double diry)
{
switch(id)
{
case 0:
case 1:
case 2:
case 3:
if(y+diry < pool[4])
return y+diry;
else
return pool[4];
case 4:
case 5:
case 6:
case 7:
if(y+diry > pool[1])
return y+diry;
else
return pool[1];
default:
return 0;
}
return 0;
}
double Scene_edit_box_item_priv::applyZ(int id, double z, double dirz)
{
switch(id)
{
case 1:
case 2:
case 5:
case 6:
if(z+dirz < pool[5])
return z+dirz;
else
return pool[5];
case 0:
case 3:
case 4:
case 7:
if(z+dirz > pool[2])
return z+dirz;
else
return pool[2];
default:
return 0;
}
return 0;
}
//type : 0 = vertex, 1 = edge, 2 = face
void Scene_edit_box_item_priv::picking(int& type, int& id, Viewer_interface *viewer)
{
viewer->makeCurrent();
type = -1;
id = -1;
int deviceWidth = viewer->camera()->screenWidth();
int deviceHeight = viewer->camera()->screenHeight();
QOpenGLFramebufferObject* fbo = new QOpenGLFramebufferObject(deviceWidth, deviceHeight,QOpenGLFramebufferObject::Depth);
fbo->bind();
viewer->glEnable(GL_DEPTH_TEST);
viewer->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QColor bgColor(viewer->backgroundColor());
//draws the image in the fbo
viewer->setBackgroundColor(::Qt::white);
draw_picking(viewer);
int rowLength = deviceWidth * 4; // data asked in RGBA,so 4 bytes.
const static int dataLength = rowLength * deviceHeight;
GLubyte* buffer = new GLubyte[dataLength];
// Qt uses upper corner for its origin while GL uses the lower corner.
viewer->glReadPixels(picked_pixel.x(), deviceHeight-1-picked_pixel.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
//decode ID and pick (don't forget the case nothing is picked
if(!(buffer[0]==buffer[1] && buffer[1]==buffer[2]))
{
int r(std::ceil((buffer[0]-10)/20)), g(std::ceil((buffer[1]-10)/20)), b(std::ceil((buffer[2]-10)/20));
id = (std::max)(r,g);
id = (std::max)(id,b);
if(buffer[0] > 0)
{
if(id <8)
type = 0 ;
}
else if(buffer[1] > 0)
{
if(id <12)
{
type = 1;
}
}
else if(buffer[2] > 0)
{
if(id <6)
{
type = 2;
}
}
}
delete[] buffer;
viewer->setBackgroundColor(bgColor);
fbo->release();
delete fbo;
}
void Scene_edit_box_item::drawHl(Viewer_interface* viewer)const
{
GLfloat offset_factor;
GLfloat offset_units;
QMatrix4x4 f_matrix;
for (int i=0; i<16; ++i){
f_matrix.data()[i] = (float)d->frame->matrix()[i];
}
GLdouble d_mat[16];
QMatrix4x4 mvp_mat;
viewer->camera()->getModelViewProjectionMatrix(d_mat);
for (int i=0; i<16; ++i)
mvp_mat.data()[i] = GLfloat(d_mat[i]);
mvp_mat = mvp_mat*f_matrix;
QMatrix4x4 mv_mat;
viewer->camera()->getModelViewMatrix(d_mat);
for (int i=0; i<16; ++i)
mv_mat.data()[i] = GLfloat(d_mat[i]);
mv_mat = mv_mat*f_matrix;
QVector4D light_pos(0.0f,0.0f,1.0f, 1.0f );
light_pos = light_pos*f_matrix;
QVector4D ambient(0.4f, 0.4f, 0.4f, 0.4f);
// Diffuse
QVector4D diffuse(1.0f, 1.0f, 1.0f, 1.0f);
// Specular
QVector4D specular(0.0f, 0.0f, 0.0f, 1.0f);
if(d->hl_type == Scene_edit_box_item_priv::VERTEX)
{
vaos[Scene_edit_box_item_priv::S_Spheres]->bind();
attribBuffers(viewer, PROGRAM_SPHERES);
d->program = getShaderProgram(PROGRAM_SPHERES, viewer);
d->program->bind();
d->program->setUniformValue("mvp_matrix", mvp_mat);
d->program->setUniformValue("mv_matrix", mv_mat);
d->program->setUniformValue("light_pos", light_pos);
d->program->setAttributeValue("colors", QColor(Qt::yellow));
double radius =std::sqrt(
(point(6,0) - point(0,0)) * (point(6,0) - point(0,0)) +
(point(6,1) - point(0,1)) * (point(6,1) - point(0,1)) +
(point(6,2) - point(0,2)) * (point(6,2) - point(0,2))) *0.02 ;
d->program->setAttributeValue("radius", radius);
d->program->setUniformValue("is_clipbox_on", false);
viewer->glDrawArraysInstanced(GL_TRIANGLES, 0,
static_cast<GLsizei>(d->vertex_spheres.size()/3),
static_cast<GLsizei>(d->hl_vertex.size()/3));
d->program->release();
vaos[Scene_edit_box_item_priv::S_Spheres]->release();
}
else if(d->hl_type == Scene_edit_box_item_priv::EDGE)
{
vaos[Scene_edit_box_item_priv::S_Edges]->bind();
if(!viewer->isOpenGL_4_3())
{
d->program = getShaderProgram(PROGRAM_WITHOUT_LIGHT);
attribBuffers(viewer, PROGRAM_WITHOUT_LIGHT);
d->program->bind();
d->program->setUniformValue("is_clipbox_on", false);
}
else
{
attribBuffers(viewer, PROGRAM_SOLID_WIREFRAME);
d->program = getShaderProgram(PROGRAM_SOLID_WIREFRAME);
d->program->bind();
QVector2D vp(viewer->width(), viewer->height());
d->program->setUniformValue("viewport", vp);
d->program->setUniformValue("near",(GLfloat)viewer->camera()->zNear());
d->program->setUniformValue("far",(GLfloat)viewer->camera()->zFar());
d->program->setUniformValue("width", 6.0f);
}
d->program->setUniformValue("f_matrix", f_matrix);
d->program->setAttributeValue("colors", QColor(Qt::yellow));
viewer->glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(d->hl_vertex.size()/3));
vaos[Scene_edit_box_item_priv::S_Edges]->release();
d->program->release();
}
else if(d->hl_type == Scene_edit_box_item_priv::FACE)
{
viewer->glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &offset_factor);
viewer->glGetFloatv(GL_POLYGON_OFFSET_UNITS, &offset_units);
viewer->glEnable(GL_BLEND);
viewer->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
vaos[Scene_edit_box_item_priv::S_Faces]->bind();
d->program = &d->transparent_face_program;
d->program->bind();
d->program->setUniformValue("mvp_matrix", mvp_mat);
d->program->setUniformValue("mv_matrix", mv_mat);
d->program->setUniformValue("light_pos", light_pos);
d->program->setUniformValue("light_diff",diffuse);
d->program->setUniformValue("light_spec", specular);
d->program->setUniformValue("light_amb", ambient);
d->program->setUniformValue("spec_power", 51.8f);
d->program->setUniformValue("is_clipbox_on", false);
d->program->setAttributeValue("colors", QColor(128,128,0,128));
viewer->glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(d->hl_vertex.size()/3));
vaos[Scene_edit_box_item_priv::S_Faces]->release();
d->program->release();
viewer->glPolygonOffset(offset_factor, offset_units);
viewer->glDisable(GL_BLEND);
}
}
void Scene_edit_box_item::drawTransparent(CGAL::Three::Viewer_interface*viewer)const
{
if (!are_buffers_filled)
{
d->computeElements();
d->initializeBuffers(viewer);
}
QMatrix4x4 f_matrix;
for (int i=0; i<16; ++i){
f_matrix.data()[i] = (float)d->frame->matrix()[i];
}
GLdouble d_mat[16];
QMatrix4x4 mvp_mat;
viewer->camera()->getModelViewProjectionMatrix(d_mat);
for (int i=0; i<16; ++i)
mvp_mat.data()[i] = GLfloat(d_mat[i]);
mvp_mat = mvp_mat*f_matrix;
QMatrix4x4 mv_mat;
viewer->camera()->getModelViewMatrix(d_mat);
for (int i=0; i<16; ++i)
mv_mat.data()[i] = GLfloat(d_mat[i]);
mv_mat = mv_mat*f_matrix;
QVector4D light_pos(0.0f,0.0f,1.0f, 1.0f );
light_pos = light_pos*f_matrix;
QVector4D ambient(0.4f, 0.4f, 0.4f, 0.4f);
// Diffuse
QVector4D diffuse(1.0f, 1.0f, 1.0f, 1.0f);
// Specular
QVector4D specular(0.0f, 0.0f, 0.0f, 1.0f);
viewer->glEnable(GL_BLEND);
viewer->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
vaos[Scene_edit_box_item_priv::Faces]->bind();
d->program = &d->transparent_face_program;
d->program->bind();
d->program->setUniformValue("mvp_matrix", mvp_mat);
d->program->setUniformValue("mv_matrix", mv_mat);
d->program->setUniformValue("light_pos", light_pos);
d->program->setUniformValue("light_diff",diffuse);
d->program->setUniformValue("light_spec", specular);
d->program->setUniformValue("light_amb", ambient);
d->program->setUniformValue("spec_power", 51.8f);
d->program->setUniformValue("is_clipbox_on", false);
d->program->setAttributeValue("colors", QColor(128,128,128,128));
viewer->glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(d->vertex_faces.size()/3));
vaos[Scene_edit_box_item_priv::Faces]->release();
d->program->release();
viewer->glDisable(GL_BLEND);
}