diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index beeb5907486..b4b2ba4d1e3 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -359,9 +359,9 @@ public: if (m_points_of_face.size()<3) { - std::cerr<<"PB: you try to triangulate a face with "< @@ -24,10 +24,12 @@ #include #include +#include +#include #ifdef CGAL_USE_BASIC_VIEWER -#ifdef __GNUC__ +#ifdef __GNUC__ #if __GNUC__ >= 9 # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wdeprecated-copy" @@ -44,7 +46,7 @@ #include #include -#ifdef __GNUC__ +#ifdef __GNUC__ #if __GNUC__ >= 9 # pragma GCC diagnostic pop #endif @@ -52,6 +54,7 @@ #include #include +#include #include #include @@ -68,14 +71,14 @@ const char vertex_source_color[] = "attribute highp vec4 vertex;\n" "attribute highp vec3 normal;\n" "attribute highp vec3 color;\n" - + "uniform highp mat4 mvp_matrix;\n" "uniform highp mat4 mv_matrix; \n" - + "varying highp vec4 fP; \n" "varying highp vec3 fN; \n" "varying highp vec4 fColor; \n" - + "uniform highp float point_size; \n" "void main(void)\n" "{\n" @@ -93,25 +96,23 @@ const char fragment_source_color[] = "varying highp vec4 fP; \n" "varying highp vec3 fN; \n" "varying highp vec4 fColor; \n" - "uniform vec4 light_pos; \n" - "uniform vec4 light_diff; \n" - "uniform vec4 light_spec; \n" - "uniform vec4 light_amb; \n" + "uniform 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" - " vec3 L = light_pos.xyz - fP.xyz; \n" - " vec3 V = -fP.xyz; \n" - - " vec3 N = normalize(fN); \n" + " highp vec3 N = normalize(fN); \n" " L = normalize(L); \n" " V = normalize(V); \n" - " vec3 R = reflect(-L, N); \n" - " vec4 diffuse = max(dot(N,L), 0.0) * light_diff * fColor; \n" - " vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; \n" - + " highp vec3 R = reflect(-L, N); \n" + " highp vec4 diffuse = max(dot(N,L), 0.0) * light_diff * fColor; \n" + " highp vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; \n" "gl_FragColor = light_amb*fColor + diffuse ; \n" "} \n" "\n" @@ -142,6 +143,93 @@ const char fragment_source_p_l[] = "} \n" "\n" }; + +//------------------------------------------------------------------------------ +// compatibility shaders + +const char vertex_source_color_comp[] = + { + "attribute highp vec4 vertex;\n" + "attribute highp vec3 normal;\n" + "attribute highp vec3 color;\n" + + "uniform highp mat4 mvp_matrix;\n" + "uniform highp mat4 mv_matrix; \n" + + "varying highp vec4 fP; \n" + "varying highp vec3 fN; \n" + "varying highp vec4 fColor; \n" + + "uniform highp float point_size; \n" + "void main(void)\n" + "{\n" + " fP = mv_matrix * vertex; \n" + " highp mat3 mv_matrix_3; \n" + " mv_matrix_3[0] = mv_matrix[0].xyz; \n" + " mv_matrix_3[1] = mv_matrix[1].xyz; \n" + " mv_matrix_3[2] = mv_matrix[2].xyz; \n" + " fN = mv_matrix_3* normal; \n" + " fColor = vec4(color, 1.0); \n" + " gl_PointSize = point_size;\n" + " gl_Position = mvp_matrix * vertex;\n" + "}" + }; + +const char fragment_source_color_comp[] = + { + "varying highp vec4 fP; \n" + "varying highp vec3 fN; \n" + "varying highp vec4 fColor; \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 highp 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 = max(dot(N,L), 0.0) * light_diff * fColor; \n" + " highp vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; \n" + + "gl_FragColor = light_amb*fColor + diffuse ; \n" + "} \n" + "\n" + }; + +const char vertex_source_p_l_comp[] = + { + "attribute highp vec4 vertex;\n" + "attribute highp vec3 color;\n" + "uniform highp mat4 mvp_matrix;\n" + "varying highp vec4 fColor; \n" + "uniform highp float point_size; \n" + "void main(void)\n" + "{\n" + " gl_PointSize = point_size;\n" + " fColor = vec4(color, 1.0); \n" + " gl_Position = mvp_matrix * vertex;\n" + "}" + }; + +const char fragment_source_p_l_comp[] = + { + "varying highp vec4 fColor; \n" + "void main(void) { \n" + "gl_FragColor = fColor; \n" + "} \n" + "\n" + }; + + + //------------------------------------------------------------------------------ inline CGAL::Color get_random_color(CGAL::Random& random) { @@ -157,7 +245,7 @@ inline CGAL::Color get_random_color(CGAL::Random& random) } //------------------------------------------------------------------------------ class Basic_viewer_qt : public CGAL::QGLViewer -{ +{ public: typedef CGAL::Exact_predicates_inexact_constructions_kernel Local_kernel; typedef Local_kernel::Point_3 Local_point; @@ -170,18 +258,28 @@ public: bool draw_edges=true, bool draw_faces=true, bool use_mono_color=false, - bool inverse_normal=false) : + bool inverse_normal=false, + bool draw_rays=true, + bool draw_lines=true, + bool draw_text=true) : CGAL::QGLViewer(parent), m_draw_vertices(draw_vertices), m_draw_edges(draw_edges), + m_draw_rays(draw_rays), + m_draw_lines(draw_lines), m_draw_faces(draw_faces), m_flatShading(true), m_use_mono_color(use_mono_color), m_inverse_normal(inverse_normal), + m_draw_text(draw_text), m_size_points(7.), - m_size_edges(3.1), + m_size_edges(3.1), + m_size_rays(3.1), + m_size_lines(3.1), m_vertices_mono_color(200, 60, 60), m_edges_mono_color(0, 0, 0), + m_rays_mono_color(0, 0, 0), + m_lines_mono_color(0, 0, 0), m_faces_mono_color(60, 60, 200), m_ambient_color(0.6f, 0.5f, 0.5f, 0.5f), m_are_buffers_initialized(false), @@ -203,6 +301,24 @@ public: &m_bounding_box, &arrays[COLOR_SEGMENTS], nullptr, nullptr), + m_buffer_for_mono_rays(&arrays[POS_MONO_RAYS], + nullptr, + &m_bounding_box, + nullptr, nullptr), + m_buffer_for_colored_rays(&arrays[POS_COLORED_RAYS], + nullptr, + &m_bounding_box, + &arrays[COLOR_RAYS], + nullptr, nullptr), + m_buffer_for_mono_lines(&arrays[POS_MONO_RAYS], + nullptr, + &m_bounding_box, + nullptr, nullptr), + m_buffer_for_colored_lines(&arrays[POS_COLORED_LINES], + nullptr, + &m_bounding_box, + &arrays[COLOR_LINES], + nullptr, nullptr), m_buffer_for_mono_faces(&arrays[POS_MONO_FACES], nullptr, &m_bounding_box, @@ -212,7 +328,7 @@ public: m_buffer_for_colored_faces(&arrays[POS_COLORED_FACES], nullptr, &m_bounding_box, - &arrays[COLOR_FACES], + &arrays[COLOR_FACES], &arrays[FLAT_NORMAL_COLORED_FACES], &arrays[SMOOTH_NORMAL_COLORED_FACES]) { @@ -229,7 +345,7 @@ public: for (unsigned int i=0; i @@ -293,23 +426,91 @@ public: template void add_point(const KPoint& p, const CGAL::Color& acolor) - { m_buffer_for_colored_points.add_point(p, acolor); } - + { m_buffer_for_colored_points.add_point(p, acolor); } + template void add_segment(const KPoint& p1, const KPoint& p2) { m_buffer_for_mono_segments.add_segment(p1, p2); } - + template void add_segment(const KPoint& p1, const KPoint& p2, const CGAL::Color& acolor) - { m_buffer_for_colored_segments.add_segment(p1, p2, acolor); } + { m_buffer_for_colored_segments.add_segment(p1, p2, acolor); } + + template + void update_bounding_box_for_ray(const KPoint &p, const KVector &v) { + // m_buffer_for_mono_points.add_point(p); + Local_point lp = internal::get_local_point(p); + Local_vector lv = internal::get_local_vector(v); + CGAL::Bbox_3 b = (lp + lv).bbox(); + m_bounding_box += b; + // m_bounding_box += CGAL::Bbox_3(b.xmin(), 0, b.ymin(), b.xmax(), 0, + // b.ymax()); + } + + template + void update_bounding_box_for_line(const KPoint &p, const KVector &v, + const KVector &pv) + { + Local_point lp = internal::get_local_point(p); + Local_vector lv = internal::get_local_vector(v); + Local_vector lpv = internal::get_local_vector(pv); + + CGAL::Bbox_3 b = lp.bbox() + (lp + lv).bbox() + (lp + lpv).bbox(); + m_bounding_box += b; + } + + /* template + void add_ray(const KPoint &p, const KVector &v) + { + double bigNumber = 1e30; + m_buffer_for_mono_rays.add_ray_segment(p, (p + (bigNumber)*v)); + } + + template + void add_ray(const KPoint &p, const KVector &v, const CGAL::Color &acolor) + { + double bigNumber = 1e30; + m_buffer_for_colored_rays.add_ray_segment(p, (p + (bigNumber)*v), acolor); + } + + template + void add_line(const KPoint &p, const KVector &v) + { + double bigNumber = 1e30; + m_buffer_for_mono_lines.add_line_segment((p - (bigNumber)*v), + (p + (bigNumber)*v)); + } + + template + void add_line(const KPoint &p, const KVector &v, const CGAL::Color &acolor) + { + double bigNumber = 1e30; + m_buffer_for_colored_lines.add_line_segment((p - (bigNumber)*v), + (p + (bigNumber)*v), acolor); + }*/ + + template + void add_text(const KPoint& kp, const QString& txt) + { + Local_point p=internal::get_local_point(kp); + m_texts.push_back(std::make_tuple(p, txt)); + } + + template + void add_text(const KPoint& kp, const char* txt) + { add_text(kp, QString(txt)); } + + template + void add_text(const KPoint& kp, const std::string& txt) + { add_text(kp, txt.c_str()); } bool is_a_face_started() const { return m_buffer_for_mono_faces.is_a_face_started() || m_buffer_for_colored_faces.is_a_face_started(); } - + void face_begin() { if (is_a_face_started()) @@ -318,7 +519,7 @@ public: } else { m_buffer_for_mono_faces.face_begin(); } - } + } void face_begin(const CGAL::Color& acolor) { @@ -339,7 +540,7 @@ public: { return m_buffer_for_colored_faces.add_point_in_face(kp); } return false; } - + template bool add_point_in_face(const KPoint& kp, const KVector& p_normal) { @@ -363,27 +564,36 @@ protected: { rendering_program_face.removeAllShaders(); rendering_program_p_l.removeAllShaders(); - + // Create the buffers for (unsigned int i=0; icompileSourceCode(vertex_source_p_l)) + if(!vertex_shader_p_l->compileSourceCode(source_)) { std::cerr<<"Compiling vertex source FAILED"<compileSourceCode(fragment_source_p_l)) + if(!fragment_shader_p_l->compileSourceCode(source_)) { std::cerr<<"Compiling fragmentsource FAILED"<compileSourceCode(vertex_source_color)) + if(!vertex_shader_face->compileSourceCode(source_)) { std::cerr<<"Compiling vertex source FAILED"<compileSourceCode(fragment_source_color)) + if(!fragment_shader_face->compileSourceCode(source_)) { std::cerr<<"Compiling fragmentsource FAILED"<(arrays[POS_MONO_RAYS].size()*sizeof(float))); + rendering_program_p_l.enableAttributeArray("vertex"); + rendering_program_p_l.setAttributeArray("vertex",GL_FLOAT,0,3); + + buffers[bufn].release(); + + rendering_program_p_l.disableAttributeArray("color"); + + vao[VAO_MONO_RAYS].release(); + + // 3.2) Color rays + + vao[VAO_COLORED_RAYS].bind(); + + ++bufn; + assert(bufn(arrays[POS_COLORED_RAYS].size()*sizeof(float))); + rendering_program_p_l.enableAttributeArray("vertex"); + rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); + + buffers[bufn].release(); + + ++bufn; + assert(bufn(arrays[COLOR_RAYS].size()*sizeof(float))); + rendering_program_p_l.enableAttributeArray("color"); + rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3); + buffers[bufn].release(); + + vao[VAO_COLORED_RAYS].release(); + + rendering_program_p_l.release(); + + // 4) LINES SHADER + // 4.1) Mono lines + vao[VAO_MONO_LINES].bind(); + + ++bufn; + assert(bufn(arrays[POS_MONO_LINES].size()*sizeof(float))); + rendering_program_p_l.enableAttributeArray("vertex"); + rendering_program_p_l.setAttributeArray("vertex",GL_FLOAT,0,3); + + buffers[bufn].release(); + + rendering_program_p_l.disableAttributeArray("color"); + + vao[VAO_MONO_LINES].release(); + + // 4.2 Color lines + + vao[VAO_COLORED_LINES].bind(); + + ++bufn; + assert(bufn(arrays[POS_COLORED_LINES].size()*sizeof(float))); + rendering_program_p_l.enableAttributeArray("vertex"); + rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); + + buffers[bufn].release(); + + ++bufn; + assert(bufn(arrays[COLOR_LINES].size()*sizeof(float))); + rendering_program_p_l.enableAttributeArray("color"); + rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3); + buffers[bufn].release(); + + vao[VAO_COLORED_LINES].release(); + + rendering_program_p_l.release(); + + // 5) FACE SHADER rendering_program_face.bind(); - // 3.1) Mono faces + // 5.1) Mono faces vao[VAO_MONO_FACES].bind(); - // 3.1.1) points of the mono faces + // 5.1.1) points of the mono faces ++bufn; assert(bufn(arrays[POS_COLORED_FACES].size()*sizeof(float))); rendering_program_face.enableAttributeArray("vertex"); rendering_program_face.setAttributeBuffer("vertex",GL_FLOAT,0,3); - + buffers[bufn].release(); - - // 3.2.2) normals of the color faces + + // 5.2.2) normals of the color faces ++bufn; assert(bufn(arrays[COLOR_FACES].size()*sizeof(float))); rendering_program_face.enableAttributeArray("color"); rendering_program_face.setAttributeBuffer("color",GL_FLOAT,0,3); - + buffers[bufn].release(); - + vao[VAO_COLORED_FACES].release(); - + rendering_program_face.release(); - + m_are_buffers_initialized = true; } @@ -602,12 +912,12 @@ protected: QMatrix4x4 mvMatrix; double mat[16]; viewer->camera()->getModelViewProjectionMatrix(mat); - for(int i=0; i < 16; i++) + for(unsigned int i=0; i < 16; i++) { mvpMatrix.data()[i] = (float)mat[i]; } viewer->camera()->getModelViewMatrix(mat); - for(int i=0; i < 16; i++) + for(unsigned int i=0; i < 16; i++) { mvMatrix.data()[i] = (float)mat[i]; } @@ -624,13 +934,13 @@ protected: CGAL::Bbox_3 bb; if (bb==bounding_box()) // Case of "empty" bounding box - { + { bb=Local_point(CGAL::ORIGIN).bbox(); bb=bb + Local_point(1,1,1).bbox(); // To avoid a warning from Qglviewer } else { bb=bounding_box(); } - + QVector4D position((bb.xmax()-bb.xmin())/2, (bb.ymax()-bb.ymin())/2, bb.zmax(), 0.0); @@ -654,13 +964,18 @@ protected: rendering_program_face.setUniformValue(mvpLocation, mvpMatrix); rendering_program_face.setUniformValue(mvLocation, mvMatrix); rendering_program_face.release(); - + rendering_program_p_l.bind(); int mvpLocation2 = rendering_program_p_l.uniformLocation("mvp_matrix"); rendering_program_p_l.setUniformValue(mvpLocation2, mvpMatrix); rendering_program_p_l.release(); } + // Returns true if the data structure lies on a plane + bool is_two_dimensional() { + return (!is_empty() && (has_zero_x() || has_zero_y() || has_zero_z())); + } + virtual void draw() { glEnable(GL_DEPTH_TEST); @@ -682,7 +997,7 @@ protected: rendering_program_p_l.setUniformValue("point_size", GLfloat(m_size_points)); glDrawArrays(GL_POINTS, 0, static_cast(arrays[POS_MONO_POINTS].size()/3)); vao[VAO_MONO_POINTS].release(); - + vao[VAO_COLORED_POINTS].bind(); if (m_use_mono_color) { @@ -736,6 +1051,83 @@ protected: rendering_program_p_l.release(); } + if(m_draw_rays) + { + rendering_program_p_l.bind(); + + vao[VAO_MONO_RAYS].bind(); + color.setRgbF((double)m_rays_mono_color.red()/(double)255, + (double)m_rays_mono_color.green()/(double)255, + (double)m_rays_mono_color.blue()/(double)255); + rendering_program_p_l.setAttributeValue("color",color); + glLineWidth(m_size_rays); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_MONO_RAYS].size()/3)); + vao[VAO_MONO_RAYS].release(); + + vao[VAO_COLORED_RAYS].bind(); + if (m_use_mono_color) + { + color.setRgbF((double)m_rays_mono_color.red()/(double)255, + (double)m_rays_mono_color.green()/(double)255, + (double)m_rays_mono_color.blue()/(double)255); + rendering_program_p_l.disableAttributeArray("color"); + rendering_program_p_l.setAttributeValue("color",color); + } + else + { + rendering_program_p_l.enableAttributeArray("color"); + } + glLineWidth(m_size_rays); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_COLORED_RAYS].size()/3)); + vao[VAO_COLORED_RAYS].release(); + + rendering_program_p_l.release(); + } + + if(m_draw_lines) + { + rendering_program_p_l.bind(); + + vao[VAO_MONO_LINES].bind(); + color.setRgbF((double)m_lines_mono_color.red()/(double)255, + (double)m_lines_mono_color.green()/(double)255, + (double)m_lines_mono_color.blue()/(double)255); + rendering_program_p_l.setAttributeValue("color",color); + glLineWidth(m_size_lines); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_MONO_LINES].size()/3)); + vao[VAO_MONO_LINES].release(); + + rendering_program_p_l.release(); + + vao[VAO_COLORED_LINES].bind(); + if (m_use_mono_color) + { + color.setRgbF((double)m_rays_mono_color.red()/(double)255, + (double)m_rays_mono_color.green()/(double)255, + (double)m_rays_mono_color.blue()/(double)255); + rendering_program_p_l.disableAttributeArray("color"); + rendering_program_p_l.setAttributeValue("color",color); + } + else + { + rendering_program_p_l.enableAttributeArray("color"); + } + glLineWidth(m_size_lines); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_COLORED_LINES].size()/3)); + vao[VAO_COLORED_LINES].release(); + + rendering_program_p_l.release(); + } + + // Fix Z-fighting by drawing faces at a depth + GLfloat offset_factor; + GLfloat offset_units; + if (is_two_dimensional()) { + glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &offset_factor); + glGetFloatv(GL_POLYGON_OFFSET_UNITS, &offset_units); + glPolygonOffset(0.1f, 0.9f); + } + if (m_draw_faces) { rendering_program_face.bind(); @@ -764,10 +1156,13 @@ protected: glDrawArrays(GL_TRIANGLES, 0, static_cast(arrays[POS_COLORED_FACES].size()/3)); vao[VAO_COLORED_FACES].release(); + if (is_two_dimensional()) + glPolygonOffset(offset_factor, offset_units); + rendering_program_face.release(); } - if (!is_empty() && (has_zero_x() || has_zero_y() || has_zero_z())) + if (is_two_dimensional()) { camera()->setType(CGAL::qglviewer::Camera::ORTHOGRAPHIC); // Camera Constraint: @@ -778,11 +1173,26 @@ protected: if (has_zero_x()) { cx=1.; } else if (has_zero_y()) { cy=1.; } else { cz=1.; } - - camera()->setViewDirection(CGAL::qglviewer::Vec(-cx,-cy,-cz)); - constraint.setRotationConstraintDirection(CGAL::qglviewer::Vec(cx, cy, cz)); + + camera()->setViewDirection(CGAL::qglviewer::Vec(cx,cy,cz)); + constraint.setRotationConstraintDirection(CGAL::qglviewer::Vec(-cx, -cy, -cz)); camera()->frame()->setConstraint(&constraint); } + + if (m_draw_text) + { + glDisable(GL_LIGHTING); + for (std::size_t i=0; iprojectedCoordinatesOf + (CGAL::qglviewer::Vec(std::get<0>(m_texts[i]).x(), + std::get<0>(m_texts[i]).y(), + std::get<0>(m_texts[i]).z())); + + drawText((int)screenPos[0], (int)screenPos[1], std::get<1>(m_texts[i])); + } + glEnable(GL_LIGHTING); + } } virtual void redraw() @@ -790,7 +1200,7 @@ protected: initialize_buffers(); update(); } - + virtual void init() { // Restore previous viewer state. @@ -806,6 +1216,8 @@ protected: setKeyDescription(::Qt::Key_G, "Switch between flat/Gouraud shading display"); setKeyDescription(::Qt::Key_M, "Toggles mono color"); setKeyDescription(::Qt::Key_N, "Inverse direction of normals"); + setKeyDescription(::Qt::Key_T, "Toggles text display"); + setKeyDescription(::Qt::Key_U, "Move camera direction upside down"); setKeyDescription(::Qt::Key_V, "Toggles vertices display"); setKeyDescription(::Qt::Key_Plus, "Increase size of edges"); setKeyDescription(::Qt::Key_Minus, "Decrease size of edges"); @@ -829,7 +1241,7 @@ protected: CGAL::Bbox_3 bb; if (bb==bounding_box()) // Case of "empty" bounding box - { + { bb=Local_point(CGAL::ORIGIN).bbox(); bb=bb + Local_point(1,1,1).bbox(); // To avoid a warning from Qglviewer } @@ -853,7 +1265,7 @@ protected: { arrays[k][i]=-arrays[k][i]; } } } - + virtual void keyPressEvent(QKeyEvent *e) { const ::Qt::KeyboardModifiers modifiers = e->modifiers(); @@ -863,8 +1275,7 @@ protected: m_draw_edges=!m_draw_edges; displayMessage(QString("Draw edges=%1.").arg(m_draw_edges?"true":"false")); update(); - } - else if ((e->key()==::Qt::Key_F) && (modifiers==::Qt::NoButton)) + }else if ((e->key()==::Qt::Key_F) && (modifiers==::Qt::NoButton)) { m_draw_faces=!m_draw_faces; displayMessage(QString("Draw faces=%1.").arg(m_draw_faces?"true":"false")); @@ -892,6 +1303,36 @@ protected: negate_all_normals(); redraw(); } + else if ((e->key()==::Qt::Key_U) && (modifiers==::Qt::NoButton)) + { + if (is_two_dimensional()) + { + displayMessage(QString("Move camera direction upside down.")); + CGAL::qglviewer::Vec cur=camera()->viewDirection(); + /* double cx=cur.x, cy=cur.y, cz=cur.z; + if (has_zero_x()) { cx=-cx; } + else if (has_zero_y()) { cy=-cy; } + else { cz=-cz; } */ + double cx=0., cy=0., cz=0.; + if (has_zero_x()) { cx=(cur.x<0?-1.:1); } + else if (has_zero_y()) { cy=(cur.y<0?-1.:1); } + else { cz=(cur.z<0?-1.:1); } + + camera()->setUpVector(-camera()->upVector()); + //camera()->frame()->setConstraint(NULL); + // camera()->setViewDirection(CGAL::qglviewer::Vec(-cx,-cy,-cz)); + //constraint.setRotationConstraintDirection(CGAL::qglviewer::Vec(cx, cy, cz)); + //camera()->frame()->setConstraint(&constraint); + //update(); + redraw(); + } + } + else if ((e->key()==::Qt::Key_T) && (modifiers==::Qt::NoButton)) + { + m_draw_text=!m_draw_text; + displayMessage(QString("Draw text=%1.").arg(m_draw_text?"true":"false")); + update(); + } else if ((e->key()==::Qt::Key_V) && (modifiers==::Qt::NoButton)) { m_draw_vertices=!m_draw_vertices; @@ -1036,16 +1477,23 @@ protected: protected: bool m_draw_vertices; bool m_draw_edges; + bool m_draw_rays; + bool m_draw_lines; bool m_draw_faces; bool m_flatShading; bool m_use_mono_color; bool m_inverse_normal; + bool m_draw_text; double m_size_points; double m_size_edges; + double m_size_rays; + double m_size_lines; CGAL::Color m_vertices_mono_color; CGAL::Color m_edges_mono_color; + CGAL::Color m_rays_mono_color; + CGAL::Color m_lines_mono_color; CGAL::Color m_faces_mono_color; QVector4D m_ambient_color; @@ -1063,12 +1511,18 @@ protected: POS_COLORED_POINTS, POS_MONO_SEGMENTS, POS_COLORED_SEGMENTS, + POS_MONO_RAYS, + POS_COLORED_RAYS, + POS_MONO_LINES, + POS_COLORED_LINES, POS_MONO_FACES, POS_COLORED_FACES, END_POS, BEGIN_COLOR=END_POS, COLOR_POINTS=BEGIN_COLOR, COLOR_SEGMENTS, + COLOR_RAYS, + COLOR_LINES, COLOR_FACES, END_COLOR, BEGIN_NORMAL=END_COLOR, @@ -1085,20 +1539,28 @@ protected: Buffer_for_vao m_buffer_for_colored_points; Buffer_for_vao m_buffer_for_mono_segments; Buffer_for_vao m_buffer_for_colored_segments; + Buffer_for_vao m_buffer_for_mono_rays; + Buffer_for_vao m_buffer_for_colored_rays; + Buffer_for_vao m_buffer_for_mono_lines; + Buffer_for_vao m_buffer_for_colored_lines; Buffer_for_vao m_buffer_for_mono_faces; Buffer_for_vao m_buffer_for_colored_faces; - + static const unsigned int NB_VBO_BUFFERS=(END_POS-BEGIN_POS)+ (END_COLOR-BEGIN_COLOR)+2; // +2 for 2 vectors of normals QGLBuffer buffers[NB_VBO_BUFFERS]; // The following enum gives the indices of the differents vao. - enum + enum { VAO_MONO_POINTS=0, VAO_COLORED_POINTS, VAO_MONO_SEGMENTS, VAO_COLORED_SEGMENTS, + VAO_MONO_RAYS, + VAO_COLORED_RAYS, + VAO_MONO_LINES, + VAO_COLORED_LINES, VAO_MONO_FACES, VAO_COLORED_FACES, NB_VAO_BUFFERS @@ -1107,6 +1569,8 @@ protected: QOpenGLShaderProgram rendering_program_face; QOpenGLShaderProgram rendering_program_p_l; + + std::vector > m_texts; }; } // End namespace CGAL diff --git a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Minimal_quadrangulation.h b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Minimal_quadrangulation.h index 7cbf278aa47..40c48ded209 100644 --- a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Minimal_quadrangulation.h +++ b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Minimal_quadrangulation.h @@ -120,7 +120,7 @@ public: // reprensenting a hole) m_mark_T=m_original_map.get_new_mark(); m_mark_L=m_original_map.get_new_mark(); - m_mark_hole=get_map().get_new_mark(); + m_mark_perforated=get_map().get_new_mark(); /* std::cout<<"Number of darts in m_map: "<(res.back()), + m_mark_perforated)) + { res.push_back(get_second_dart_of_the_path + (path[i], path.get_ith_flip(i)), true); } } } res.update_is_closed(); @@ -717,7 +723,7 @@ protected: get_map().template basic_link_beta_for_involution<2>(d1, d2); origin_to_copy[it]=d1; copy_to_origin[d1]=it; - get_map().mark(d2, m_mark_hole); + get_map().mark(d2, m_mark_perforated); } else if (typename Map::Dart_const_handle(it)< m_original_map.template beta<2>(it)) @@ -732,9 +738,9 @@ protected: copy_to_origin[d2]=m_original_map.template beta<2>(it); if (m_original_map.is_perforated(it)) - { get_map().mark(d1, m_mark_hole); } + { get_map().mark(d1, m_mark_perforated); } if (m_original_map.is_perforated(m_original_map.template beta<2>(it))) - { get_map().mark(d2, m_mark_hole); } + { get_map().mark(d2, m_mark_perforated); } } } } @@ -816,35 +822,40 @@ protected: for (auto it=get_map().darts().begin(), itend=get_map().darts().end(); it!=itend; ++it) { - if (!get_map().is_marked(it, grey) && !get_map().is_marked(it, m_mark_hole)) + if (!get_map().is_marked(it, grey)) { - queue.push(it); get_map().template mark_cell<2>(it, grey); - - while (!queue.empty()) + if (!get_map().is_marked(it, m_mark_perforated)) { - dh=queue.front(); - queue.pop(); - ddh=dh; - do + queue.push(it); + + while (!queue.empty()) { - if (!get_map().is_marked(get_map().template beta<2>(ddh), grey) && - !get_map().is_marked(get_map().template beta<2>(ddh), m_mark_hole)) + dh=queue.front(); // face(dh) is not perforated (and thus all its darts) + queue.pop(); + ddh=dh; + do { - get_map().mark(ddh, toremove); - get_map().mark(get_map().template beta<2>(ddh), toremove); - mark_edge(m_original_map, copy_to_origin[ddh], m_mark_L); - get_map().template mark_cell<2>(get_map().template beta<2>(ddh), - grey); - queue.push(get_map().template beta<2>(ddh)); + if (!get_map().is_marked(get_map().template beta<2>(ddh), grey) && + !get_map().is_marked(get_map().template beta<2>(ddh), + m_mark_perforated)) + { + get_map().mark(ddh, toremove); + get_map().mark(get_map().template beta<2>(ddh), toremove); + mark_edge(m_original_map, copy_to_origin[ddh], m_mark_L); + get_map().template mark_cell<2>(get_map().template beta<2>(ddh), + grey); + queue.push(get_map().template beta<2>(ddh)); + } + ddh=get_map().template beta<1>(ddh); } - ddh=get_map().template beta<1>(ddh); + while (dh!=ddh); } - while (dh!=ddh); } } } + CGAL_assertion(get_map().is_whole_map_marked(grey)); get_map().free_mark(grey); } @@ -940,12 +951,16 @@ protected: get_map().set_automatic_attributes_management(true); get_map().free_mark(toremove); + // Now we consider non perforated faces which are loop. + // The edges of these faces are marked as if they belong to T (the spanning + // tree of contracted edges), i.e. they are ignored when we will transform + // a path in the original mesh into a path in the minimal surface. typename Map::Dart_const_handle origin_dart; for (typename CMap_for_minimal_quadrangulation::Dart_range::iterator it=get_map().darts().begin(), itend=get_map().darts().end(); it!=itend; ++it) { - if (!get_map().is_marked(it, m_mark_hole) && + if (!get_map().is_marked(it, m_mark_perforated) && get_map().template beta<1>(it)==it) { origin_dart=copy_to_origin[it]; @@ -955,12 +970,12 @@ protected: CGAL_assertion(m_paths.find(origin_dart)!=m_paths.end()); m_paths.erase(origin_dart); + mark_edge(m_original_map, origin_dart, m_mark_T); + CGAL_assertion(m_paths.find(origin_dart)==m_paths.end()); if (!m_original_map.template is_free<2>(origin_dart)) { CGAL_assertion(m_paths.find(m_original_map.template beta<2> (origin_dart))==m_paths.end()); } - - mark_edge(m_original_map, origin_dart, m_mark_T); } } @@ -989,25 +1004,22 @@ protected: get_map().negate_mark(oldedges); // now all edges are marked // 1) We insert a vertex in each face which is not a hole. - // New edges created by the operation are not marked. + // New edges created by the operation are not marked oldedges. typename Map::size_type treated=get_map().get_new_mark(); for (typename CMap_for_minimal_quadrangulation::Dart_range::iterator - it=get_map().darts().begin(); it!=get_map().darts().end(); - ++it) + it=get_map().darts().begin(); it!=get_map().darts().end(); ++it) { if (!get_map().is_marked(it, treated)) { get_map().template mark_cell<2>(it, treated); if (get_map().is_marked(it, oldedges) && - !get_map().is_marked(it, m_mark_hole)) + !get_map().is_marked(it, m_mark_perforated) && + get_map().template beta<1>(it)!=it) { - if (get_map().template beta<1>(it)!=it) - { - get_map().negate_mark(treated); // To mark new darts - get_map().insert_cell_0_in_cell_2(it); - get_map().negate_mark(treated); - } + get_map().negate_mark(treated); // To mark new darts treated + get_map().insert_cell_0_in_cell_2(it); + get_map().negate_mark(treated); } } } @@ -1033,10 +1045,24 @@ protected: std::pair& p=itp->second; /* std::cout<<"Pair: "<(p.first); } - if (!get_map().is_marked(itp->second.second, m_mark_hole)) - { p.second=get_map().template beta<0>(p.second); } + if (!get_map().is_marked(p.first, m_mark_perforated) && + !get_map().is_marked(p.second, m_mark_perforated)) + { // Edge between two real faces, removed during the quadrangulation + p.first=get_map().template beta<0, 2>(p.first); + p.second=get_map().template beta<0>(p.second); + } + else if (!get_map().is_marked(p.first, m_mark_perforated)) + { // Edge between a real face and a perforated one + CGAL_assertion(get_map().template beta<2>(p.first)==p.second); // The edge was not updated in update_length_two_paths_before_edge_removals + p.second=get_map().template beta<1>(p.first); + p.first=get_map().template beta<0, 2>(p.first); + } + else if (!get_map().is_marked(p.second, m_mark_perforated)) + { + CGAL_assertion(get_map().template beta<2>(p.first)==p.second); // The edge was not updated in update_length_two_paths_before_edge_removals + p.second=get_map().template beta<0, 2>(p.first); + p.first=get_map().template beta<1>(p.first); + } /* std::cout<<" -> "<(it, m_mark_hole)); } } */ - auto toremove=get_map().get_new_mark(); - // 3) We remove all the old edges and extend the holes when necessary. + // 3) We remove all the old edges, and extend the perforated faces. for (typename CMap_for_minimal_quadrangulation::Dart_range::iterator it=get_map().darts().begin(), itend=get_map().darts().end(); it!=itend; ++it) { - if (get_map().is_dart_used(it) && get_map().is_marked(it, oldedges) && - (!get_map().is_marked(it, m_mark_hole) || - !get_map().is_marked(get_map().template beta<2>(it), m_mark_hole))) + if (get_map().is_dart_used(it) && + get_map().is_marked(it, oldedges) && + !get_map().is_marked(it, m_mark_perforated)) { - if (get_map().is_marked(get_map().template beta<2>(it), m_mark_hole) && - !get_map().is_marked(it, m_mark_hole)) - { get_map().template mark_cell<2>(it, m_mark_hole); } - else if (get_map().is_marked(it, m_mark_hole) && - !get_map().is_marked(get_map().template beta<2>(it), m_mark_hole)) - { get_map().template mark_cell<2>(get_map().template beta<2>(it), - m_mark_hole); } - // get_map().template remove_cell<1>(it); - get_map().mark(it, toremove); - get_map().mark(get_map().template beta<2>(it), toremove); + if (get_map().is_marked(get_map().template beta<2>(it), m_mark_perforated)) + { get_map().template mark_cell<2>(it, m_mark_perforated); } + get_map().template remove_cell<1>(it); + // get_map().mark(it, toremove); + // get_map().mark(get_map().template beta<2>(it), toremove); } } - for (typename TPaths::iterator itp=m_paths.begin(), itpend=m_paths.end(); - itp!=itpend; ++itp) - { - std::pair& p=itp->second; - while(get_map().is_marked(p.first, toremove)) - { p.first=get_map().template beta<2, 1>(p.first); } - while(get_map().is_marked(p.second, toremove)) - { p.second=get_map().template beta<2, 1>(p.second); } - } - - for (typename CMap_for_minimal_quadrangulation::Dart_range::iterator - it=get_map().darts().begin(), itend=get_map().darts().end(); - it!=itend; ++it) - { - if (get_map().is_dart_used(it) && get_map().is_marked(it, toremove)) - { get_map().template remove_cell<1>(it); } - } - - get_map().free_mark(toremove); - /* FOR DEBUG for (typename CMap_for_minimal_quadrangulation::Dart_range::iterator it=get_map().darts().begin(); it!=get_map().darts().end(); ++it) @@ -1221,8 +1221,12 @@ protected: ++it) { initdart=it; - if (!get_map().is_marked(initdart, toremove)) - { // Here we are on a border edge + if (!get_map().is_marked(initdart, toremove) && + !get_map().is_marked(initdart, m_mark_perforated) && + !get_map().is_marked(get_map().template beta<2>(initdart), + m_mark_perforated)) + { // Here we are on a border edge of a "real" face (i.e. non perforated) + // and adjacent to a "real" face curdart=get_map().template beta<0, 2>(initdart); while(get_map().is_marked(curdart, toremove)) { @@ -1234,14 +1238,10 @@ protected: curdart=get_map().template beta<0, 2>(curdart); } - /*if (!get_map().is_marked(get_map().template beta<2>(curdart), - m_mark_hole))*/ - { - d1=copy_to_origin.find(get_map().template beta<2>(curdart))->second; - if (m_original_map.template is_free<2>(d1) || - d1(d1)) - { m_paths[d1].second=initdart; } - } + d1=copy_to_origin.find(get_map().template beta<2>(curdart))->second; + if (m_original_map.template is_free<2>(d1) || + d1(d1)) + { m_paths[d1].second=initdart; } } } @@ -1306,7 +1306,7 @@ protected: do { ++deg; - hole_detected=hole_detected || get_map().is_marked(dh, m_mark_hole); + hole_detected=hole_detected || get_map().is_marked(dh, m_mark_perforated); dh=get_map().template beta<2, 1>(dh); } while(dh!=it); @@ -1363,7 +1363,7 @@ protected: // then we add 1 to the next dart if we dont cross a hole // and we add deg(v)+1 if we cross a hole dh=it; - while(!get_map().is_marked(dh, m_mark_hole)) + while(!get_map().is_marked(dh, m_mark_perforated)) { dh=get_map().template beta<2, 1>(dh); } @@ -1377,7 +1377,7 @@ protected: // this is for the turn V3 get_map().info(ddh)=id; #endif // CGAL_PWRLE_TURN_V2 - if (get_map().is_marked(get_map().template beta<2>(ddh), m_mark_hole)) + if (get_map().is_marked(get_map().template beta<2>(ddh), m_mark_perforated)) { id+=get_map().template info<0>(ddh)+1; } else { id+=1; } @@ -1551,7 +1551,7 @@ protected: { if (get_map().number_of_darts()!=4) { return false; } - return (get_map().number_of_marked_darts(m_mark_hole)==0); + return (get_map().number_of_marked_darts(m_mark_perforated)==0); } /// Test if m_paths are valid, i.e.: @@ -1684,7 +1684,7 @@ protected: /// (except the edges that belong to the spanning tree T). std::size_t m_mark_T; /// mark each edge of m_original_map that belong to the spanning tree T std::size_t m_mark_L; /// mark each edge of m_original_map that belong to the dual spanning tree L - std::size_t m_mark_hole; /// mark each edge of m_map that bounds a hole + std::size_t m_mark_perforated; /// mark each edge of m_map that bounds a hole #ifdef CGAL_PWRLE_TURN_V2 TDartIds m_dart_ids; /// Ids of each dart of the transformed map, between 0 and n-1 (n being the number of darts)