// Copyright (c) 2022 GeometryFactory Sarl (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // Author(s): Guillaume Damiand // Mostafa Ashraf #ifndef CGAL_GRAPHICS_SCENE_H #define CGAL_GRAPHICS_SCENE_H // TODO #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace CGAL { //------------------------------------------------------------------------------ inline CGAL::IO::Color get_random_color(CGAL::Random& random) { CGAL::IO::Color res; do { res=CGAL::IO::Color(random.get_int(0,256), random.get_int(0,256), random.get_int(0,256)); } while(res.red()==255 && res.green()==255 && res.blue()==255); return res; } //------------------------------------------------------------------------------ // This class is responsible for dealing with available CGAL data structures and // handling buffers. class Graphics_scene { public: using BufferType=float; typedef CGAL::Exact_predicates_inexact_constructions_kernel Local_kernel; typedef Local_kernel::Point_3 Local_point; typedef Local_kernel::Vector_3 Local_vector; Graphics_scene() : m_buffer_for_points(&arrays[POS_POINTS], nullptr, &m_bounding_box, &arrays[COLOR_POINTS]), m_buffer_for_segments(&arrays[POS_SEGMENTS], nullptr, &m_bounding_box, &arrays[COLOR_SEGMENTS]), m_buffer_for_rays(&arrays[POS_RAYS], nullptr, &m_bounding_box, &arrays[COLOR_RAYS]), m_buffer_for_lines(&arrays[POS_RAYS], nullptr, &m_bounding_box, &arrays[COLOR_LINES]), m_buffer_for_faces(&arrays[POS_FACES], nullptr, &m_bounding_box, &arrays[COLOR_FACES], &arrays[FLAT_NORMAL_FACES], &arrays[SMOOTH_NORMAL_FACES]), m_default_color_face(60, 60, 200), m_default_color_point(200, 60, 60), m_default_color_segment(0, 0, 0), m_default_color_ray(0, 0, 0), m_default_color_line(0, 0, 0) {} inline const CGAL::IO::Color &get_default_color_face() const { return m_default_color_face; } inline const CGAL::IO::Color &get_default_color_point() const { return m_default_color_point; } inline const CGAL::IO::Color &get_default_color_segment() const { return m_default_color_segment; } inline const CGAL::IO::Color &get_default_color_ray() const { return m_default_color_ray; } inline const CGAL::IO::Color &get_default_color_line() const { return m_default_color_line; } inline const Buffer_for_vao &get_buffer_for_points() const { return m_buffer_for_points; } inline void set_default_color_face(const CGAL::IO::Color& c) { m_default_color_face = c; } inline void set_default_color_point(const CGAL::IO::Color& c) { m_default_color_point = c; } inline void set_default_color_segment(const CGAL::IO::Color& c) { m_default_color_segment = c; } inline void set_default_color_ray(const CGAL::IO::Color& c) { m_default_color_ray = c; } inline void set_default_color_line(const CGAL::IO::Color& c) { m_default_color_line = c; } inline const Buffer_for_vao &get_buffer_for_segments() const { return m_buffer_for_segments; } inline const Buffer_for_vao &get_buffer_for_rays() const { return m_buffer_for_rays; } inline const Buffer_for_vao &get_buffer_for_lines() const { return m_buffer_for_lines; } inline const Buffer_for_vao &get_buffer_for_faces() const { return m_buffer_for_faces; } const CGAL::Bbox_3 &bounding_box() const { return m_bounding_box; } const std::vector &get_array_of_index(int index) const { assert(index(arrays[index].size()*sizeof(BufferType)); } unsigned int number_of_elements(int index) const { return static_cast(arrays[index].size()/3); } void initiate_bounding_box(const CGAL::Bbox_3& new_bounding_box) { m_bounding_box = new_bounding_box; } void update_bounding_box(const CGAL::Bbox_3 &box) { m_bounding_box+=box; } template void update_bounding_box_for_ray(const KPoint &p, const KVector &v) { Local_point lp = get_local_point(p); Local_vector lv = get_local_vector(v); update_bounding_box((lp + lv).bbox()); } template void update_bounding_box_for_line(const KPoint &p, const KVector &v, const KVector &pv) { Local_point lp = get_local_point(p); Local_vector lv = get_local_vector(v); Local_vector lpv = get_local_vector(pv); update_bounding_box(lp.bbox() + (lp + lv).bbox() + (lp + lpv).bbox()); } void reverse_all_normals() const { m_buffer_for_faces.negate_normals(); } template void add_point(const KPoint &p) { m_buffer_for_points.add_point(p, m_default_color_point); } template void add_point(const KPoint &p, const CGAL::IO::Color &acolor) { m_buffer_for_points.add_point(p, acolor); } template void add_segment(const KPoint &p1, const KPoint &p2) { m_buffer_for_segments.add_segment(p1, p2, m_default_color_segment); } template void add_segment(const KPoint &p1, const KPoint &p2, const CGAL::IO::Color &acolor) { m_buffer_for_segments.add_segment(p1, p2, acolor); } template void add_ray(const KPoint &p, const KVector &v) { double bigNumber = 1e30; m_buffer_for_rays.add_ray_segment(p, (p + (bigNumber)*v), m_default_color_ray); } template void add_ray(const KPoint &p, const KVector &v, const CGAL::IO::Color &acolor) { double bigNumber = 1e30; m_buffer_for_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_lines.add_line_segment((p - (bigNumber)*v), (p + (bigNumber)*v), m_default_color_line); } template void add_line(const KPoint &p, const KVector &v, const CGAL::IO::Color &acolor) { double bigNumber = 1e30; m_buffer_for_lines.add_line_segment((p - (bigNumber)*v), (p + (bigNumber)*v), acolor); } template bool add_point_in_face(const KPoint &kp) { if (m_buffer_for_faces.is_a_face_started()) { return m_buffer_for_faces.add_point_in_face(kp); } return false; } template bool add_point_in_face(const KPoint &kp, const KVector &p_normal) { if (m_buffer_for_faces.is_a_face_started()) { return m_buffer_for_faces.add_point_in_face(kp, p_normal); } return false; } bool a_face_started() const { return m_buffer_for_faces.is_a_face_started(); } void face_begin() { if (a_face_started()) { std::cerr << "You cannot start a new face before to finish the previous one." << std::endl; } else { m_buffer_for_faces.face_begin(m_default_color_face); } } void face_begin(const CGAL::IO::Color &acolor) { if (a_face_started()) { std::cerr << "You cannot start a new face before to finish the previous one." << std::endl; } else { m_buffer_for_faces.face_begin(acolor); } } void face_end() { if (m_buffer_for_faces.is_a_face_started()) { m_buffer_for_faces.face_end(); } } template void add_text(const KPoint &kp, const std::string &txt) { Local_point p = 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, std::string(txt)); } bool empty() const { return (m_buffer_for_points.is_empty() && m_buffer_for_segments.is_empty() && m_buffer_for_rays.is_empty() && m_buffer_for_lines.is_empty() && m_buffer_for_faces.is_empty()); } bool has_zero_x() const { return m_buffer_for_points.has_zero_x() && m_buffer_for_segments.has_zero_x() && m_buffer_for_faces.has_zero_x() && m_buffer_for_rays.has_zero_x() && m_buffer_for_lines.has_zero_x(); } bool has_zero_y() const { return m_buffer_for_points.has_zero_y() && m_buffer_for_segments.has_zero_y() && m_buffer_for_faces.has_zero_y() && m_buffer_for_rays.has_zero_y() && m_buffer_for_lines.has_zero_y(); } bool has_zero_z() const { return m_buffer_for_points.has_zero_z() && m_buffer_for_segments.has_zero_z() && m_buffer_for_faces.has_zero_z() && m_buffer_for_rays.has_zero_z() && m_buffer_for_lines.has_zero_z(); } // Returns true if the data structure lies on a XY or XZ or YZ plane bool is_two_dimensional() const { return (!empty() && (has_zero_x() || has_zero_y() || has_zero_z())); } void clear() { m_buffer_for_points.clear(); m_buffer_for_segments.clear(); m_buffer_for_rays.clear(); m_buffer_for_lines.clear(); m_buffer_for_faces.clear(); m_texts.clear(); m_bounding_box=CGAL::Bbox_3(); } template static Local_point get_local_point(const KPoint &p) { return internal::Geom_utils::Kernel, Local_kernel>::get_local_point(p); } template static Local_vector get_local_vector(const KVector &v) { return internal::Geom_utils::Kernel, Local_kernel>::get_local_vector(v); } void m_texts_clear() { m_texts.clear(); } std::size_t m_texts_size() const { return m_texts.size(); } const std::vector>& get_m_texts() const { return m_texts; } public: // The following enum gives the indices of different elements of arrays // vectors. enum Buffers { BEGIN_POS = 0, POS_POINTS = BEGIN_POS, POS_SEGMENTS, POS_RAYS, POS_LINES, POS_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, SMOOTH_NORMAL_FACES = BEGIN_NORMAL, FLAT_NORMAL_FACES, END_NORMAL, LAST_INDEX = END_NORMAL }; protected: Buffer_for_vao m_buffer_for_points; Buffer_for_vao m_buffer_for_segments; Buffer_for_vao m_buffer_for_rays; Buffer_for_vao m_buffer_for_lines; Buffer_for_vao m_buffer_for_faces; CGAL::IO::Color m_default_color_face; CGAL::IO::Color m_default_color_point; CGAL::IO::Color m_default_color_segment; CGAL::IO::Color m_default_color_ray; CGAL::IO::Color m_default_color_line; std::vector> m_texts; std::vector arrays[LAST_INDEX]; CGAL::Bbox_3 m_bounding_box; }; } // namespace CGAL #endif // CGAL_GRAPHICS_SCENE_H